Skip to main content
GameDev.net gamedev.net
🔒 Locked

Rotating a Polygon

Started by ACAC Aug 5, 2002 at 4:28 PM 5 replies 800+ views
Original Post
ACAC
ACAC
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();
}

[code]

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"  i dont want to use them, this way I will learn more

Thanks for your help in advance     
algumacoisaqualquer
algumacoisaqualquer
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]
ACAC
ACAC
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);
ACAC
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 :-)


  
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;
}
ACAC
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 :-)


  
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;
}
ACAC
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 :-)


  
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;
}
grhodes_at_work
grhodes_at_work
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

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.