Advertisement

Rotating a Polygon

Started by August 05, 2002 04:28 PM
5 comments, last by ACAC 22 years, 6 months ago
I decided to write my own rotation function for my sprites in dx8, i cant manage to get it working, i use a textured square
// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** //
// Description  : m_SetRotation sets the angle of the sprite.
// Parameters   : angle - the angle to rotate to.
// Return Values: none.
// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** //
void CSpriteInstance::m_setRotation(float angle)
{
	if(m_VB)
	{
		m_VB->Release();
		m_VB = NULL;
	}
	//convert to rads
	angle = angle * (D3DX_PI/180);


	//center of the sprite X and Y
	float center_x, center_y;

	center_x =  m_Vertices[1].x  - (m_width/2);
	center_y =  m_Vertices[3].y  - (m_height/2);

	//calculate the hypot
	float hyp = (squ(m_width/2) + squ(m_height/2));
	hyp = sqrt(hyp);

	m_Vertices[0].x = center_x - sin(angle) * hyp;
	m_Vertices[0].y = center_y - cos(angle) * hyp;

	m_Vertices[1].x = center_x + sin(angle) * hyp;
	m_Vertices[1].y = center_y - cos(angle) * hyp;

	m_Vertices[2].x = center_x + sin(angle) * hyp;
	m_Vertices[2].y = center_y + cos(angle) * hyp;

	m_Vertices[3].x = center_x - sin(angle) * hyp;
	m_Vertices[3].y = center_y + cos(angle) * hyp;

	//create the vertex buffer
	pTemplate->pDevice->CreateVertexBuffer(4*sizeof(FVF2D), 0, FVF2D_FORMAT,
									 D3DPOOL_DEFAULT, &m_VB);

	VOID* pVertices = NULL;

	//lock and copy the square
	m_VB->Lock(0, sizeof(m_Vertices), (BYTE**)&pVertices, 0);

	memcpy(pVertices, m_Vertices, sizeof(m_Vertices));

	//unlock
	m_VB->Unlock();
}



I calculate the center of the sprite, then using pythagorams threum i calculate the lenght of the hypotenuse, I then use the center to calculate the new positions of each vertex.
this is the order of the vertices
topleft[0]
topright[1]
bottomright[2]
bottomleft[3]

Before anyone starts saying use matrices, then id like to say "no" <img src="smile.gif" width=15 height=15 align=middle> i dont want to use them, this way I will learn more

Thanks for your help in advance <img src="smile.gif" width=15 height=15 align=middle>    </pre> 
Didn't tested it, I don't actually think it will work but...


ok, imagine that we make a cartesian plane centered in center_x, center_y.
now we take m_Vertices[1] and trace a line to the center.
That angle is Alpha.
we need also:
Hypot = sqrt(m_Vertices[1].y^2 + m_Vertices[1].x^2);
Now:
Alpha = asin(m_Vertices[1].y - center_y/Hypot);
Temp = acos(m_Vertices[1].y - center_y/Hypot);
// To get a 2*Pi angle

if (Temp < 0 && Alpha > 0){Alpha += 2*(Alpha - D3DX_PI/4);}
if (Temp < 0 && Alpha < 0){Alpha -= 2*(Alpha + D3DX_PI/4);}
//that's some cheating to make it a 2*Pi degree
//Anyway, if this doesen't work try to get the Alpha Value

//Now, the angle you want to rotate:
Alpha += Angle;
m_Vertices[0].x = center_x + sin(D3DX_PI - Alpha) * hyp;
m_Vertices[0].y = center_y - cos(D3DX_PI - Alpha) * hyp;

m_Vertices[1].x = center_x + sin(Alpha) * hyp;
m_Vertices[1].y = center_y + cos(Alpha) * hyp;

m_Vertices[2].x = center_x - sin( - Alpha) * hyp;
m_Vertices[2].y = center_y + cos( - Alpha) * hyp;

m_Vertices[3].x = center_x - sin(D3DX_PI + Alpha) * hyp;
m_Vertices[3].y = center_y - cos(D3DX_PI + Alpha) * hyp;

Well, tell me what happends.

[edited by - algumacoisaqualquer on August 5, 2002 7:04:18 PM]
Advertisement
I couldnt get it to work, however it now rotates around
x = 0, y = 0

how can i get it to rotate around the objects center?
Heres the code I use:

	angle = angle * (D3DX_PI/180);	fcos = cos(angle);	fsin = sin(angle);	//center of the sprite X and Y	float center_x, center_y;	center_x =  m_Vertices[1].x  - (m_width/2);	center_y =  m_Vertices[3].y  - (m_height/2);	//calculate the hypot	float hyp = (squ(m_width/2) + squ(m_height/2));	hyp = sqrt(hyp);	m_Vertices[0].x = (m_Vertices[0].x * fcos) - (m_Vertices[0].y * fsin);	m_Vertices[0].y = (m_Vertices[0].x * fsin) + (m_Vertices[0].y * fcos);	m_Vertices[1].x = (m_Vertices[1].x * fcos) - (m_Vertices[1].y * fsin);	m_Vertices[1].y = (m_Vertices[1].x * fsin) + (m_Vertices[1].y * fcos);	m_Vertices[2].x = (m_Vertices[2].x * fcos) - (m_Vertices[2].y * fsin);	m_Vertices[2].y = (m_Vertices[2].x * fsin) + (m_Vertices[2].y * fcos);	m_Vertices[3].x = (m_Vertices[3].x * fcos) - (m_Vertices[3].y * fsin);	m_Vertices[3].y = (m_Vertices[3].x * fsin) + (m_Vertices[3].y * fcos); 
OK This time ive got it to stay in the same place, but for some reason the polygon scales ( by getting smaller ) each time i call the function, heres the new code :-)


      float fcos = 0, fsin = 0;	//convert to rads	angle = angle * (D3DX_PI/180.0f);	//calculate cos/sin	fcos = cos(angle);	fsin = sin(angle);	float center_x = 0, center_y = 0;	float vector_x = 0,vector_y = 0;	//center of the sprite X and Y	//transform the polygon to 0,0	for(index = 0; index < 4; index++)	{		center_x +=  m_Vertices[index].x; 		center_y +=  m_Vertices[index].y; 	}	vector_x = center_x / 4;	vector_y = center_y / 4;	//transform the polygon to 0,0	for(index = 0; index < 4; index++)	{		m_Vertices[index].x -= vector_x;		m_Vertices[index].y -= vector_y;	}	//rotate the polygon	m_Vertices[0].x = (m_Vertices[0].x * fcos) - (m_Vertices[0].y * fsin);	m_Vertices[0].y = (m_Vertices[0].x * fsin) + (m_Vertices[0].y * fcos);	m_Vertices[1].x = (m_Vertices[1].x * fcos) - (m_Vertices[1].y * fsin);	m_Vertices[1].y = (m_Vertices[1].x * fsin) + (m_Vertices[1].y * fcos);	m_Vertices[2].x = (m_Vertices[2].x * fcos) - (m_Vertices[2].y * fsin);	m_Vertices[2].y = (m_Vertices[2].x * fsin) + (m_Vertices[2].y * fcos);	m_Vertices[3].x = (m_Vertices[3].x * fcos) - (m_Vertices[3].y * fsin);	m_Vertices[3].y = (m_Vertices[3].x * fsin) + (m_Vertices[3].y * fcos);	//retransform to original pos	for(index = 0; index < 4; index++)	{		m_Vertices[index].x += vector_x;		m_Vertices[index].y += vector_y;	}  
OK This time ive got it to stay in the same place, but for some reason the polygon scales ( by getting smaller ) each time i call the function, heres the new code :-)


      float fcos = 0, fsin = 0;	//convert to rads	angle = angle * (D3DX_PI/180.0f);	//calculate cos/sin	fcos = cos(angle);	fsin = sin(angle);	float center_x = 0, center_y = 0;	float vector_x = 0,vector_y = 0;	//center of the sprite X and Y	//transform the polygon to 0,0	for(index = 0; index < 4; index++)	{		center_x +=  m_Vertices[index].x; 		center_y +=  m_Vertices[index].y; 	}	vector_x = center_x / 4;	vector_y = center_y / 4;	//transform the polygon to 0,0	for(index = 0; index < 4; index++)	{		m_Vertices[index].x -= vector_x;		m_Vertices[index].y -= vector_y;	}	//rotate the polygon	m_Vertices[0].x = (m_Vertices[0].x * fcos) - (m_Vertices[0].y * fsin);	m_Vertices[0].y = (m_Vertices[0].x * fsin) + (m_Vertices[0].y * fcos);	m_Vertices[1].x = (m_Vertices[1].x * fcos) - (m_Vertices[1].y * fsin);	m_Vertices[1].y = (m_Vertices[1].x * fsin) + (m_Vertices[1].y * fcos);	m_Vertices[2].x = (m_Vertices[2].x * fcos) - (m_Vertices[2].y * fsin);	m_Vertices[2].y = (m_Vertices[2].x * fsin) + (m_Vertices[2].y * fcos);	m_Vertices[3].x = (m_Vertices[3].x * fcos) - (m_Vertices[3].y * fsin);	m_Vertices[3].y = (m_Vertices[3].x * fsin) + (m_Vertices[3].y * fcos);	//retransform to original pos	for(index = 0; index < 4; index++)	{		m_Vertices[index].x += vector_x;		m_Vertices[index].y += vector_y;	}  
OK This time ive got it to stay in the same place, but for some reason the polygon scales ( by getting smaller ) each time i call the function, heres the new code :-)


      float fcos = 0, fsin = 0;	//convert to rads	angle = angle * (D3DX_PI/180.0f);	//calculate cos/sin	fcos = cos(angle);	fsin = sin(angle);	float center_x = 0, center_y = 0;	float vector_x = 0,vector_y = 0;	//center of the sprite X and Y	//transform the polygon to 0,0	for(index = 0; index < 4; index++)	{		center_x +=  m_Vertices[index].x; 		center_y +=  m_Vertices[index].y; 	}	vector_x = center_x / 4;	vector_y = center_y / 4;	//transform the polygon to 0,0	for(index = 0; index < 4; index++)	{		m_Vertices[index].x -= vector_x;		m_Vertices[index].y -= vector_y;	}	//rotate the polygon	m_Vertices[0].x = (m_Vertices[0].x * fcos) - (m_Vertices[0].y * fsin);	m_Vertices[0].y = (m_Vertices[0].x * fsin) + (m_Vertices[0].y * fcos);	m_Vertices[1].x = (m_Vertices[1].x * fcos) - (m_Vertices[1].y * fsin);	m_Vertices[1].y = (m_Vertices[1].x * fsin) + (m_Vertices[1].y * fcos);	m_Vertices[2].x = (m_Vertices[2].x * fcos) - (m_Vertices[2].y * fsin);	m_Vertices[2].y = (m_Vertices[2].x * fsin) + (m_Vertices[2].y * fcos);	m_Vertices[3].x = (m_Vertices[3].x * fcos) - (m_Vertices[3].y * fsin);	m_Vertices[3].y = (m_Vertices[3].x * fsin) + (m_Vertices[3].y * fcos);	//retransform to original pos	for(index = 0; index < 4; index++)	{		m_Vertices[index].x += vector_x;		m_Vertices[index].y += vector_y;	}  
Advertisement
quote:
Original post by ACAC
OK This time ive got it to stay in the same place, but for some reason the polygon scales ( by getting smaller ) each time i call the function, heres the new code :-)



I''ll tell you why. Your transformation code (shown below for just one vertex) has a bug.

quote:
Original post by ACAC
m_Vertices[0].x = (m_Vertices[0].x * fcos) - (m_Vertices[0].y * fsin);
m_Vertices[0].y = (m_Vertices[0].x * fsin) + (m_Vertices[0].y * fcos);



And the problem is this. You''re modifying m_Vertices[index].x and then using the modified value to calculate m_Vertices[index].y when you should be using the previous, unmodified value of m_Vertices[index].x. That code is equivalent to the following:

quote:
Original post by ACAC
m_Vertices[0].x = (m_Vertices[0].x * fcos) - (m_Vertices[0].y * fsin);

new_x = m_Vertices[0].x;

m_Vertices[0].y = (new_x * fsin) + (m_Vertices[0].y * fcos);



You should have code like this instead to properly rotate:

quote:
Original post by ACAC
old_x = m_Vertices[0].x;
m_Vertices[0].x = (old_x * fcos) - (m_Vertices[0].y * fsin);
m_Vertices[0].y = (old_x * fsin) + (m_Vertices[0].y * fcos);



So, your complete set of transformation should be:


  	old_x = m_Vertices[0].x;	m_Vertices[0].x = (old_x * fcos) - (m_Vertices[0].y * fsin);	m_Vertices[0].y = (old_x * fsin) + (m_Vertices[0].y * fcos);	old_x = m_Vertices[1].x;	m_Vertices[1].x = (old_x * fcos) - (m_Vertices[1].y * fsin);	m_Vertices[1].y = (old_x * fsin) + (m_Vertices[1].y * fcos);	old_x = m_Vertices[2].x;	m_Vertices[2].x = (old_x * fcos) - (m_Vertices[2].y * fsin);	m_Vertices[2].y = (old_x * fsin) + (m_Vertices[2].y * fcos);	old_x = m_Vertices[3].x;	m_Vertices[3].x = (old_x * fcos) - (m_Vertices[3].y * fsin);	m_Vertices[3].y = (old_x * fsin) + (m_Vertices[3].y * fcos);  


Everything else looks perfectly fine. I didn''t check your later dx8 code, so I don''t know what''s wrong with that. For DX8 specific problems, you should visit the DirectX forum.

Graham Rhodes
Senior Scientist
Applied Research Associates, Inc.
Graham Rhodes Moderator, Math & Physics forum @ gamedev.net

This topic is closed to new replies.

Advertisement