OpenGL Rotation Origin Problems

Started by
3 comments, last by CaptainRedmuff 15 years, 7 months ago
Hi guys, I've had a browse around and can't seem to find any mention of this, i'm starting to make progress with learning OpenGL, but theres one thing thats totally throwing me off for the time being. Maybe someone will be kind enough to shed some light on this for me. Currently, i am simply rendering a textured rectangle to the screen. I was thumbing through tutorials and wanted to improve my rendering by adding in some rotation and possibly throw in some alpha blending when i came across this post http://www.iphonedevsdk.com/forum/iphone-sdk-development/2060-how-extend-texture2d-opacity.html Huzzah i thought, as i happily modded my blitting method to include rotations and was presented with a slightly rotated object, but all was not as expected. For some reason (which i'm sure is totally obvious), the rectangle is rotated about the top left point, ie: 0.0, 0.0 which is really what i would expect, 0.0, 0.0 being the origin and all... but i want my object to be rotated around its center point, not the origin of the screen. I have set up my glOrthof and glViewport for landscape orientation as such:

glViewport(0.0, 0.0, backingWidth, backingHeight);

//other stuff here

glOrthof(0.0, backingHeight, backingWidth, 0.0, -1.0, 1.0);
This gives me a landscape orientation with the top left coords being 0.0, 0.0 and bottom right being 480.0, 320.0 which is my prefered coordinate system. As of such, this appears to be the main origin for all object rotations, which isn't really what i want. Is there any way i can translate an objects origin to rotate around its center point? for example, if i were to render the rect:

my_rect = CGRectMake(backingWidth / 4, backingHeight / 4, backingWidth / 2, backingHeight / 2);
a small rect half the width and height of the device would be presented directly in the center of the screen. Any rotations made to this however would be about the origin of 0.0, 0.0 of the screen and not the object itself. Is there any way to fix this so that the object would rotate around its center piont, in this example being the center of the screen? I dont mind changing the coordinate system if needs be, but i would still prefer to use the current 0.0, 0.0, 480.0, 320.0 landscape orientation as opposed to -1.0, 1.0, 1.0, -1.0 unless of course it would be a feasible endeavour to write a utility function to convert between the two coordinate systems when rendering? It seems that rotations must be made around the origin of the screen/device (0.0, 0.0) but surely that can't be the case as not every object/model rendered is required to rotate around the origin, but rather its own origin, if that makes sense? Is there a way to set the rotation origin, or translate the object to the screen origin, rotate and back again? Using the coordinate system 0.0, 0.0, 480.0, 320.0 for landscape orientation works perfectly, but obviously this issue with rotating objects around the origin is completely holding up any progress i can make. Please, if anyone knows of a method, or any tutorials that can outline what must be done, i would be very grateful for any help you guys can throw my way :) Just for completeness, the code i'm using for rotation is:

glRotate(rotation, 0.0, 0.0, 1.0);
Simple as it may seem, that one single line has caused me a weekend of headaches and very little progress. I'm positive there must be a way to fix this, can anyone point me in the right direction please? Any help would be greatly appreciated, thanks for reading
Advertisement
May I suggest you pass the origin as a parameter to your blitting function, that way you won't allways be limited to having the origin at the center. All you would need to do then is subtract the origin position from the sprites position. Heres my simple sprite drawing function which is working perfectly fine for my current project.

/////////////////////////////////////////////////////////////////////////////////////////// DrawSprite()/////////////////////////////////////////////////////////////////////////////////////////void DrawSprite(Texture texture, Vector2 position, Rect source, Colour tint, Vector2 origin, float angle){	glPushMatrix();	glLoadIdentity();	glTranslatef(position.X, position.Y, 0.0f);	glRotatef(angle, 0.0f, 0.0f, 1.0f);	glBindTexture(GL_TEXTURE_2D, texture.TextureID());	glBegin(GL_QUADS);	glColor3f(tint.r, tint.g, tint.b);	glTexCoord2f((float)source.X / texture.Width(), (float)source.Y / texture.Height());	glVertex2f(-origin.X, -origin.Y);	glTexCoord2f((float)(source.X+source.Width)/texture.Width(), (float)source.Y/texture.Height());	glVertex2f(-origin.X+(float)source.Width, -origin.Y);	glTexCoord2f((float)(source.X+source.Width)/texture.Width(), (float)(source.Y+source.Height)/texture.Height());	glVertex2f(-origin.X+(float)source.Width, -origin.Y+(float)source.Height);	glTexCoord2f((float)source.X / texture.Width(), (float)(source.Y+source.Height)/texture.Height());	glVertex2f(-origin.X, -origin.Y+(float)source.Height);	glEnd();	glBindTexture(GL_TEXTURE_2D, NULL);	glPopMatrix();}


EDIT: Added correct function ^^

[Edited by - cNoob on September 16, 2008 5:06:17 PM]
Hi cNoob, thank you for your reply :)

I've modified my rendering function to include the call to glTranslatef(), but this hasn't yielded the results i was expecting :(

It seems that my texture is still being rotated incorrectly around the top left origin of the rect i am passing to my rendering function. I've pasted the function below for reference:

//draw texture in rect with rotation- (void)drawInRect:(CGRect)rect withOrigin:(CGPoint)origin withRotation:(GLfloat)rotation{	//calculate texture coordinates	GLfloat coordinates[] = {0.0, textureMaxT,							textureMaxS, textureMaxT,							0.0, 0.0,							textureMaxS, 0.0};		//calculate texture vertices	GLfloat vertices[] = {rect.origin.x, rect.origin.y, 0.0,							rect.origin.x + rect.size.width, rect.origin.y, 0.0,							rect.origin.x, rect.origin.y + rect.size.height, 0.0,							rect.origin.x + rect.size.width, rect.origin.y + rect.size.height, 0.0,};	//push the matrix onto the stack	glPushMatrix();		//load identity	glLoadIdentity();		//translate the verticies	glTranslatef(rect.origin.x - origin.x, rect.origin.y -  origin.y, 0.0);		//rotate texture around the z axis	glRotatef(rotation, 0.0, 0.0, 1.0);		//bind the texture to the target	glBindTexture(GL_TEXTURE_2D, textureName);		//set the texture verticies	glVertexPointer(3, GL_FLOAT, 0, vertices);		//set the texture coordinates	glTexCoordPointer(2, GL_FLOAT, 0, coordinates);		//render primitive from texture data	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);		//pop the matrix off of the stack	glPopMatrix();}


My projection is set to use the coordinate system (0.0, 0.0, 480.0, 320.0) where (0.0, 0.0) is the top left of the screen and (480.0, 320.0) is the bottom right.

When calling the function, i am passing a rect which matches the screen dimensions (as above), a 2D point and a rotation value as such:

[MyImageManager drawImage:myImage inRect:CGRectMake(0.0, 0.0, 480.0, 320.0) withOrigin:CGPointMake(240.0, 160.0) withRotation:10.0];


What i currently see on screen in only 1/4 of my rect/texture with the other 3/4's rendered off the top left hand corners of the screen (if that makes sense?) but it also seems that the rotation is still taking place around the top left origin (0.0, 0.0) of the rect itself, rather than the coords i passed through the origin variable.

Perhaps i should be modifying my vertices array to include the origin values? I'm currently drawing blanks on this one, perhaps you can advise?

if i can figure out the syntax for this forum, i will try to post a screen shot to further illustrate my problem.

Thanks again for reading and thanks for your previous reply.
Woops, thats what I get for having two solutions with the same name (different locations ><), I've fixed the old code block in the previous post with the correct version.

// Also, you can post an image using the <b>img</b> html tag:<img src="http://link.to.image/screenshot.png">// and you can post code in a neat block using: (without spaces)[ source ]code goes here[ /source ] 


:)
Hi cNoob,

Thanks again for your reply. I'm not at my mac right now (currently at work) but ill be sure to modify my rendering function when i return home.

Your method looks very similar to the previous one your posted (before editing), although your call to glTranslatef() doesn't take into account the position of the texture but i assume this is canceled out by the changes made when constructing your vertices? (using glVertex2f()) ?

I found a post on another forum which said:

1. translate the point of rotation so that it sits at the origin
2. rotate
3. translate back

and the code would look something like this

void rotate2D(float angle, float pointOfRotationX, float pointOfRotationY)
{
// Note that the steps here are in the reverse order of that mentioned above!!
// That's because openGL transformations post-multiply the matrices.
glTranslatef(pointOfRotationX, pointOfRotationY, 0.0f);
glRotatef(angle, 0.0f, 0.0f, 1.0f);
glTranslatef(-pointOfRotationX, -pointOfRotationY, 0.0f);
}

I think i may be styarting to understand the cause of the problem a lot more now, which should hopefully help me identify the solution but i may have to brush up on my knowledge of matrices (its been a few years since i used OpenGL and even then i only scratched the surface).

Thanks for your help and your code snippet, it really is appreciated, ill be sure to post again if i run into any further problems :)

This topic is closed to new replies.

Advertisement