How to rotate model not camera in OpenGL? - opengl

I have the same qustion as in the title :/
I make something like:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0f, 0, -zoom);
glRotatef(yr*20+moveYr*20, 0.0f, 1.0f, 0.0f);
glRotatef(zr*20+moveZr*20, 1.0f, 0.0f, 0.0f);
//Here model render :/
And in my app camera is rotating not model :/

Presumably the reason you believe it's your camera moving and not your model is because all the objects in the scene are moving together?
After rendering your model and before rendering other objects, are you resetting the MODELVIEW matrix? In other words, are you doing another glLoadIdentity() or glPopMatrix() after you render the model you're talking about and before rendering other objects?
Because if not, whatever transformations you applied to that model will also apply to other objects rendered, and it will be as if you rotated the whole world (or the camera).
I think there may be another problem with your code though:
glTranslatef(0.0f, 0, -zoom);
glRotatef(yr*20+moveYr*20, 0.0f, 1.0f, 0.0f);
glRotatef(zr*20+moveZr*20, 1.0f, 0.0f, 0.0f);
//Here model render :/
Are you trying to rotate your model around the point (0, 0, -zoom)?
Normally, in order to rotate around a certain point (x,y,z), you do:
Translate (x,y,z) to the origin (0,0,0) by translating by the vector (-x,-y,-z)
Perform rotations
Translate the origin back to (x,y,z) by translating by the vector (x,y,z)
Draw
If you are trying to rotate around the point (0,0,zoom), you are missing step 3.
So try adding this before you render your model:
glTranslatef(0.0f, 0, zoom); // translate back from origin
On the other hand if you are trying to rotate the model around the origin (0,0,0), and also move it along the z-axis, then you will want your translation to come after your rotation, as #nonVirtual said.
And don't forget to reset the MODELVIEW matrix before you draw other objects. So the whole sequence would be something like:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
#if you want to rotate around (0, 0, -zoom):
glTranslatef(0.0f, 0, -zoom);
glRotatef(yr*20+moveYr*20, 0.0f, 1.0f, 0.0f);
glRotatef(zr*20+moveZr*20, 1.0f, 0.0f, 0.0f);
glTranslatef(0.0f, 0, zoom); // translate back from origin
#else if you want to rotate around (0, 0, 0):
glRotatef(yr*20+moveYr*20, 0.0f, 1.0f, 0.0f);
glRotatef(zr*20+moveZr*20, 1.0f, 0.0f, 0.0f);
glTranslatef(0.0f, 0, -zoom);
#endif
//Here model render :/
glLoadIdentity();
// translate/rotate for other objects if necessary
// draw other objects

You use GL_MODELVIEW when defining the transformation for your objects and GL_PROJECTION to transform your viewpoint.

I believe it has to do with the order in which you are applying your transformations. Try switching the order of the call to glRotate and glTranslate. As it is now you are moving it outward from the origin, then rotating it about the origin, which will give the appearance of the object orbiting around the camera. If you instead rotate it while it is still at the origin, then move it, it should give you the desired result. Hope that helps.

Related

Why does this OpenGL rotation also translate my object?

I'm trying to rotate an object (an arrow) which has it's default position as pointing to the right. I've been looking around and I'm using the glLoadIdentity() and glPushMatrix() and glPopMatrix() as a way to only rotate the object in my glBegin function and not the whole scene:
glLoadIdentity();
glPushMatrix();
glRotatef(5, 0.0f, 0.0f, 1.0f);
glBegin(GL_TRIANGLE_FAN);
glColor3f(1.0f, 0.0f, 1.0f);
glVertex2f(xx2-0.01, yy2);
glVertex2f(xx2-0.06, yy2+0.03);
glVertex2f(xx2-0.06, yy2-0.03);
glEnd();
glPopMatrix();
However, it also translates my arrow, instead of only rotating it. Do I need to translate the offset back to it's original position? Or am I doing something wrong?
SOLVED:
glLoadIdentity();
glPushMatrix();
glTranslatef(xx2, yy2, 0);
glRotatef(45, 0.0f, 0.0f, 1.0f);
glTranslatef(-xx2, -yy2, 0);
glBegin(GL_TRIANGLE_FAN);
glColor3f(1.0f, 0.0f, 1.0f);
glVertex2f(xx2-0.01, yy2);
glVertex2f(xx2-0.06, yy2+0.03);
glVertex2f(xx2-0.06, yy2-0.03);
glEnd();
glPopMatrix();
Need to translate back to center (0, 0, 0), apply the rotation and then back to it's original position (xx2, yy2, 0)
All rotations are around the origin.
So yes, if you want to rotate around some other point, you must translate from that point to the origin, rotate, and then translate back again.
Your code is correct, but you are applying your operations out of order. Specifically, you need to apply the rotation first, then apply the translation.

opengl rotate an object to set its correct face before render on screen

I am loading an object through an obj file in opengl using GLM Library but it comes out on the screen upside down. Also i am providing a capability to user so he can rotate all the objects accordingly by mouse too. e.g. zoom and zoom in and rotate with y axis.
Problem is i dont know how to rotate the object first to make its face according to what i need. After that i want to draw this object and offcourse at that time mouse can play its role to rotate it.
my draw function contain the following code
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
glTranslatef(m_fPosX, m_fPosY,-m_fZoom);
glRotatef(m_fRotX, 1.0f, 0.0f, 0.0f);//these two for mouse movement
glRotatef(m_fRotY, 0.0f, 1.0f, 0.0f);
glRotated(180,0.0f, 0.0f, -1.0f);
glDisable(GL_TEXTURE_2D);
glColor3f(0.90f,0.90f,0.90f);
glmDraw(m_p3dModel,GLM_SMOOTH | GLM_MATERIAL);
glPopMatrix();
here rotate functions are all dependent on mouse movement but if it get load upside down i dont know how to first make my object face right direction and then allow it in this draw function...Which means i need to set its face before calling this draw function.
glRotatef(m_fRotY, 1.0f, 0.0f, 0.0f);
should be
glRotatef(m_fRotY, 0.0f, 1.0f, 0.0f);
copy/paste is the mother of many evils :o)
For transformation / projection / model view tutorial : check link

Skybox rotates out of sync with world

I've got a small scene with a loaded mesh, a ground plane and a skybox. I am generating a cube, and using the vertex positions as the cubemap texture co-ordinates.
Horizontal rotation (about the y-axis) works perfectly and the world movement is aligned with the skybox. Vertical rotation (about the camera's x-axis) doesn't seem to match up with the movement of the other objects, except that the strange thing is that when the camera is looking at the center of a cube face, everything seems aligned. In other words, the movement is non-linear and I'll try my best to illustrate the effect with some images:
First, the horizontal movement which as far as I can tell is correct:
Facing forward:
Facing left at almost 45Deg:
Facing left at 90Deg:
And now the vertical movement which seems to have some discrepancy in movement:
Facing forward again:
Notice the position of the ground plane in relation to the skybox in this image. I rotated slightly left to make it more apparent that the Sun is being obscured when it shouldn't.
Facing slightly down:
Finally, a view straight up to show the view is correctly centered on the (skybox) cube face.
Facing straight up:
Here's my drawing code, with the ground plane and mesh drawing omitted for brevity. (Note that the cube in the center is a loaded mesh, and isn't generated by the same function for the skybox).
void MeshWidget::draw() {
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
glRotatef(-rot_[MOVE_CAMERA][1], 0.0f, 1.0f, 0.0f);
glRotatef(-rot_[MOVE_CAMERA][0], 1.0f, 0.0f, 0.0f);
glRotatef(-rot_[MOVE_CAMERA][2], 0.0f, 0.0f, 1.0f);
glDisable(GL_DEPTH_TEST);
glUseProgramObjectARB(shader_prog_ids_[2]);
glBindBuffer(GL_ARRAY_BUFFER, SkyBoxVBOID);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, sizeof(Vec3), BUFFER_OFFSET(0));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, SkyIndexVBOID);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0));
glUseProgramObjectARB(shader_prog_ids_[0]);
glEnable(GL_DEPTH_TEST);
glPopMatrix();
glTranslatef(0.0f, 0.0f, -4.0f + zoom_factor_);
glRotatef(rot_[MOVE_CAMERA][0], 1.0f, 0.0f, 0.0f);
glRotatef(rot_[MOVE_CAMERA][1], 0.0f, 1.0f, 0.0f);
glRotatef(rot_[MOVE_CAMERA][2], 0.0f, 0.0f, 1.0f);
glPushMatrix();
// Transform light to be relative to world, not camera.
glRotatef(rot_[MOVE_LIGHT][1], 0.0f, 1.0f, 0.0f);
glRotatef(rot_[MOVE_LIGHT][0], 1.0f, 0.0f, 0.0f);
glRotatef(rot_[MOVE_LIGHT][2], 0.0f, 0.0f, 1.0f);
float lightpos[] = {10.0f, 0.0f, 0.0f, 1.0f};
glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
glPopMatrix();
if (show_ground_) {
// Draw ground...
}
glPushMatrix();
// Transform and draw mesh...
glPopMatrix();
}
And finally, here's the GLSL code for the skybox, which generates the texture co-ordinates:
Vertex shader:
void main()
{
vec4 vVertex = vec4(gl_ModelViewMatrix * gl_Vertex);
gl_TexCoord[0].xyz = normalize(vVertex).xyz;
gl_TexCoord[0].w = 1.0;
gl_TexCoord[0].x = -gl_TexCoord[0].x;
gl_Position = gl_Vertex;
}
Fragment shader:
uniform samplerCube cubeMap;
void main()
{
gl_FragColor = texture(cubeMap, gl_TexCoord[0]);
}
I'd also like to know if using quaternions for all camera and object rotations would help.
If you need any more information (or images), please ask!
I think you should be generating your skybox texture lookup based on a worldspace vector (gl_Vertex?) not a view space vector (vVertex).
I'm assuming your skybox coordinates are already defined in worldspace as I don't see a model matrix transform before drawing it (only the camera rotations). In that case, you should be sampling the skybox texture based on the worldspace position of a vertex, it doesn't need to be transformed by the camera. You're already translating the vertex by the camera, you shouldn't need to translate the lookup vector as well.
Try replacing normalize(vVertex) with normalize(gl_Vertex) and see if that improves things.
Also I might get rid of the x = -x thing, I suspect that was put in to compensate for the fact that the texture was rotating in the wrong direction originally?
I'd also like to know if using quaternions for all camera and object rotations would help.
Help how? It doesn't offer any new functionality over using matrices. I've heard arguments both ways as to whether matrixes or quaternions have better performance, but I see no need to use them.

Removing polygons from the screen (OpenGL)?

Assuming the code is:
glLoadIdentity();
glTranslatef(-1.5f,0.0f,-6.0f);
glBegin(GL_TRIANGLES);
glVertex3f( 0.0f, 1.0f, 0.0f);
glVertex3f(-1.0f,-1.0f, 0.0f);
glVertex3f( 1.0f,-1.0f, 0.0f);
glEnd();
glLoadIdentity();
//Drawing another object...
How would I change the code to erase the object? I know that commenting out glTranslatef() will erase the triangle, but is that the formal way to do it?
If you put glClear at the start of the draw function (draw function is usually in a loop) you can simply choose not to redraw the triangle, drawing like that will leave no reference to your triangle.
Also, glTranslatef() wont remove your triangle, glTranslatef() is just a function to move the current matrix (in your case the matrix with your triangle is being moved into the camera view)
glClear()
http://www.khronos.org/opengles/documentation/opengles1_0/html/glClear.html
If you're asking how to make the triangle go away in subsequent frames, there's no need. Every frame time you're responsible for redrawing everything. OpenGL will not remember your triangle.
Putting an if around glBegin...glVertex...glEnd would be the most straightforward way.

how can I retrieve the current position of the vertices after they have been transformed?

How can I retrieve the current position of the vertices after they have been transformed? I have the following code....
How can I get the position of the "modelVertices" after the transform has been applied?
I am really after the screen coordinates so I can tell if a vert has been clicked by the mouse.
glMatrixMode(GL_MODELVIEW);
// save model transform matrix
GLfloat currentModelMatrix[16];
glGetFloatv(GL_MODELVIEW_MATRIX, currentModelMatrix);
// clear the model transform matrix
glLoadIdentity();
// rotate the x and y axis of the model transform matrix
glRotatef(rotateX, 1.0f, 0.0f, 0.0f);
glRotatef(rotateY, 0.0f, 1.0f, 0.0f);
// reapply the previous transforms
glMultMatrixf(currentModelMatrix);
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// since each vertes is defined in 3D instead of 2D parameter one has been
// upped from 2 to 3 to respect this change.
glVertexPointer(3, GL_FLOAT, 0, modelVertices);
glEnableClientState(GL_VERTEX_ARRAY);
GLU has the function gluProject() and gluUnProject():
http://www.opengl.org/sdk/docs/man/xhtml/gluProject.xml
If your platform doesn't have GLU you can always grab the code for MESA and see how it is implemented.
You could use the feedback buffer.