Cannot rotate my image around it's center in openGL - c++

I am trying to rotate an image around it's center. here is the code:
glPushMatrix();
glTranslatef(-x, -y, 0);
glRotatef(10, 0, 0, 1);
glTranslatef(x, y, 0);
glBindTexture(GL_TEXTURE_2D, img);
glBegin(GL_QUADS);
glTexCoord2i(0, 0);
glVertex2i(x, y);
glTexCoord2i(1, 0);
glVertex2i(x+width, y);
glTexCoord2i(1, 1);
glVertex2i(x+width, y+height);
glTexCoord2i(0, 1);
glVertex2i(x, y + height);
glEnd();
glPopMatrix();
I read everywhere to translate my image to the center of rotation then rotate and translate it back.
But when i tried doing it step by step I found out that when I translate and then rotate it moves the center of rotation along with the image, so it rotates around a point that is offscreen on the same distance from the image as the initial point of rotation from the initial image before translation.
Can anyone tell me why this happens or how to fix it?

Matrix-Operations and thus glTranslatef/glRotatef are applied in reversed order. So when your rotation center is c=(x,y), you have to translate along -c first, then rotate and then translate along c.
In your case, you have to exchange the two translate lines to the following:
glTranslatef(x, y, 0); //Translate back
glRotatef(10, 0, 0, 1); //Rotate
glTranslatef(-x, -y, 0); //Translate first along -c

Related

Rotating a scaled sphere with openGL

I'm attempting to draw an eclipse-shaped object so I used a sphere and scaled it as necessary. I'm attempting to rotate this eclipse-shaped object with the following code but it won't budge (or at least it doesn't look like it's budging). I've tested by simply changing to another 3D shape and it rotates. Is there something I'm doing wrong? What's so different about a glutSolidSphere?
glPushMatrix();
glTranslatef(subx, suby + y, subz);
glScalef(9.0, 1.75, 1.75);
glRotatef(angle, 0, 1, 0);
glTranslatef(-subx, -suby, -subz);
glTranslatef(subx, suby, subz);
glutSolidSphere(1.0, 50, 50);
glPopMatrix();
Issue as pointed out above in comments was that I was rotating the sphere before I stretched it. Scaling and then rotating fixed the issue.
glPushMatrix();
glTranslatef(subx, suby + y, subz);
glRotatef(angle, 0, 1, 0);
glScalef(9.0, 1.75, 1.75);
glTranslatef(-subx, -suby, -subz);
glTranslatef(subx, suby, subz);
glutSolidSphere(1.0, 50, 50);
glPopMatrix();

Drawing a sphere in a room opengl

I have the code for a room provided to me, I need to add a sphere in the room. It goes like this:
PushMatrix();
//draw floor,walls,ceilings
PushMatrix();
//draw some boxes on front wall
PopMatrix();
PushMatrix();
//drawing sphere;
glLoadIdentity();
glColor3f(1, 0, 0);
glTranslatef(0, ypos, 0);
glutSolidSphere(2, 20, 20);
PopMatrix();
PopMatrix();
But all the walls etc turn red (and no sphere) when I do this. Why does that happen even after pushing another matrix?
Calling glColor*() sets the current color. This color doesn't change before you call glColor*() again. In other words glPushMatrix() and glPopMatrix() has no effect on the current color.
Thus if you in //draw some boxes on front wall don't call glColor*(). Then due to you setting the color to red by calling glColor3f(1, 0, 0) then everything is going to be red from that point on.
Considering:
glMatrixMode(GL_PROJECTION);
gluPerspective(40, 1, 1, 40);
glMatrixMode(GL_MODELVIEW);
Then:
glPushMatrix();
glTranslatef(0, 0, -10);
glColor3f(1, 0, 0);
glutSolidSphere(2, 20, 20);
glPopMatrix();
By doing the above you should see a sphere.
Thus if you before didn't see the sphere at all. Then it's probably due to ypos being outside your view. If you were referring to the whole screen being red, then I'm assuming ypos to be around 0, which means that it would be filling the whole screen (Again assuming you don't translate the view in any other way).

How can I define starting position of glutWireCube?

I am rather new to programming so I may not use the correct terminology. I am trying to create a dog out of only glutwirecubes, however I cannot figure out how to define a starting position for the back legs, nor can I figure out how to close the space between my 'shoulder' and 'elbows'. I have each body part assigned to rotate by key press. I also realize that my use of glPushMatrix and glPopMatrix may not be correct as I do not fully understand how the matrix stack is saved/loaded.
glPushMatrix();
glTranslatef(-1, 0, 0);
glRotatef((GLfloat)body,1, 0, 0);//sets rotations about x,y,z axis
glTranslatef(1, 0, 0);
glPushMatrix();
glScalef(2.0, 0.4, 0.5);//sets dimensions of cube
glutWireCube(2.0);//sets scale of wire cube
glPopMatrix();
glPopMatrix();
glPushMatrix();
glTranslatef(-1, 0, 0);
glRotatef((GLfloat)shoulder, 0, 0, 1);//sets rotations about x,y,z axis
glTranslatef(1, 0, 0);
glPushMatrix();
glScalef(1.5, 0.4, 0.5);//sets dimensions of cube
glutWireCube(.75);//sets scale of wire cube
glPopMatrix();
glTranslatef(1,0,0);
glRotatef((GLfloat)elbow,0,0,1);//sets rotations about x,y,z axis
glTranslatef(1,0,0);
glPushMatrix();
glScalef(1.5,0.4,0.5);//sets dimensions of cube
glutWireCube(.75);//sets scale of wire cube
glPopMatrix();
glPopMatrix();
glutSwapBuffers();
The picture is the position I am aiming for, however my cubes always start oriented horizontally.
with glTranslate right before, as for its friends !
For instance you might translate so that the center is now at the corner, so that your rotations rotate around this new handle.

OpenGl Rotation around point

My problem is that I need to rotate a white square around the center of the far left end, and no matter what I try, I cannot seem to do it.
I need to rotate an object around radius, which is radius far from the position (getPosition().x/y), which i have already translated to. I need to rotate it r degrees. If it matters, I am using an orthographic (glOrtho) projection.
So far this what I tried:
//Try 1
glRotatef(r, 0, 0, 1.0f);
glTranslatef(radius, radius, 0);
glBegin(GL_QUADS)
//draw here...
//Try 2
glTranslatef(-radius, -radius, 0);
glRotatef(r, 0, 0, 1.0f);
glTranslatef(radius, radius, 0);
glBegin(GL_QUADS)
//draw here...
//Try 3
glTranslatef(radius + getPosition().x, radius + getPosition().y, 0);
glRotatef(r, 0, 0, 1.0f);
glTranslatef(radius, radius, 0);
glBegin(GL_QUADS)
//draw here...
I have tried Googling and searching on StackOverflow numerous times, with no luck. Two of these "solutions" came from answers found on StackOverflow itself.
All of these attempts rotate around the origin. I have also tried numerous other more nonsensical combinations, to no avail. If it matters, a little bit before this code, I translate the matrix (and don't pop it back out). I don't think this is the problem, as popping the matrix and pushing a new one back on right before any of these attempts does not fix the problem.
Any help would be much appreciated.
So I found the solution:
glTranslatef(radius + getPosition().x, radius + getPosition().y, 0);
glRotatef(r, 0, 0, 1.0f);
glBegin(GL_POLYGON);
It turns out you dont have to translate after the rotation, which is was several sources suggested.

OpenGL rotating a 2D texture

UPDATE
See bottom for update.
I've been looking alot around the internet and I have found a few tutorials that explain what I'm trying to achieve but I can't get it to work, either the tutorial is incomplete or not applicable on my code.
I'm trying something as simple as rotating a 2D image around its origin (center).
I use xStart, xEnd, yStart and yEnd to flip the texture which are either 0 or 1.
This is what the code looks like
GameRectangle dest = destination;
Vector2 position = dest.getPosition();
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, this->image);
//If the rotation isn't 0 we'll rotate it
if (rotation != 0)
{
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glTranslatef(0.5, 0.5, 0);
glRotatef(rotation, 0, 0, 1);
glMatrixMode(GL_PROJECTION);
}
glBegin(GL_QUADS);
glTexCoord2d(xStart,yStart);
glVertex2f(position.x, position.y);
glTexCoord2d(xEnd,yStart);
glVertex2f(position.x + this->bounds.getWidth(), position.y);
glTexCoord2d(xEnd,yEnd);
glVertex2f(position.x + this->bounds.getWidth(), position.y + this->bounds.getHeight());
glTexCoord2d(xStart,yEnd);
glVertex2f(position.x, position.y + this->bounds.getHeight());
glEnd();
glDisable(GL_TEXTURE_2D);
//Reset the rotation so next object won't be rotated
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glRotatef(0, 0, 0, 1);
glMatrixMode(GL_PROJECTION);
This code will draw the image in it's original size and it will rotate it, but it will rotate it from the top left corner which crops the image a lot. By calling GameRectangle.getOrigin() I can easily get the center of the rectangle, but I don't know where to use it.
Bit if put:
glTranslatef(-0.5, -0.5, 0);
After I call the:
glRotatef(0.5, 0.5, 0);
It will rotate from the center, but it will strech the image if it's not a perfect 90 degrees rotation.
UPDATE
After trying pretty much everything possible, I got the result I was looking for.
But I'm not sure if this is the best approach. Please tell me if there's something wrong with my code.
As I mentioned in a comment above, I use the same image multiple times and draw it with different values, so I can't save anything to the actual image. So I must reset the values everytime after I have rendered it.
I changed my code to this:
//Store the position temporary
GameRectangle dest = destination;
Vector2 position = dest.getPosition();
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, this->image);
glTranslatef(dest.getOrigin().x, dest.getOrigin().y, 0);
glRotatef(rotation, 0, 0, 1);
glBegin(GL_QUADS);
glTexCoord2d(xStart,yStart);
glVertex2f(-dest.getWidth()/2, -dest.getHeight()/2);
glTexCoord2d(xEnd,yStart);
glVertex2f(dest.getWidth()/2, -dest.getHeight()/2);
glTexCoord2d(xEnd,yEnd);
glVertex2f(dest.getWidth()/2, dest.getHeight()/2);
glTexCoord2d(xStart,yEnd);
glVertex2f(-dest.getWidth()/2, dest.getHeight()/2);
glEnd();
//Reset the rotation and translation
glRotatef(-rotation,0,0,1);
glTranslatef(-dest.getOrigin().x, -dest.getOrigin().y, 0);
glDisable(GL_TEXTURE_2D);
This rotates the texture together with the quad it's drawn in, it doesn't strech or crop. However the edges are a bit jagged if the image is filled square but I guess I can't avoid that with out antialiasing.
What you want is this:
glPushMatrix(); //Save the current matrix.
//Change the current matrix.
glTranslatef(dest.getOrigin().x, dest.getOrigin().y, 0);
glRotatef(rotation, 0, 0, 1);
glBegin(GL_QUADS);
glTexCoord2d(xStart,yStart);
glVertex2f(-dest.getWidth()/2, -dest.getHeight()/2);
glTexCoord2d(xEnd,yStart);
glVertex2f(dest.getWidth()/2, -dest.getHeight()/2);
glTexCoord2d(xEnd,yEnd);
glVertex2f(dest.getWidth()/2, dest.getHeight()/2);
glTexCoord2d(xStart,yEnd);
glVertex2f(-dest.getWidth()/2, dest.getHeight()/2);
glEnd();
//Reset the current matrix to the one that was saved.
glPopMatrix();