Opengl, render an object pose - opengl

I want to rotate a 3d object in a roll pitch yaw fashion.
I store the pose of the object in a matrix, and perform roll, pitch and yaw rotations multiplying the pose matrix by one of the standard rotation matrices about x, y, or z axis.
Then I display it using these lines of code.
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(-5, 5, 2, 0, 0, 0, 0, 1, 0);
glPushMatrix();
ship.Draw();
glPopMatrix();
glutSwapBuffers();
}
void Spacecraft::Draw(){
glMultMatrixf(pose);
model.Draw();
return;
}
It works, but the object, instead to rotate around their own axis it rotates around the world axis...
Where am I wrong?

Rotations are always about the origin of the local coordinate system. So you first have to translate the coordinate system so that the center of the desired rotation happens to be at the local coordinate system origin. It's hard to tell where and which transformations to apply without seeing the rest of your code.
The rest of the drawing code, which is not shown, also includes the contents of the model. Draw function. Most likely you've got a translations somewhere in there. This translation moves the object away from the coordinate system center. I think what you're missing (not about OpenGL but linear algebra in general) is, that matrix multiplication is non-commutative, i.e. order of operations matter and that for column major matrices the order of operations is last to first (or right to left if written in normal notation). So the rotation must be the last thing you multiply on the matrix, not the first.

Related

OpenGL chained translations/rotations

I have a generic OpenGL 3D world, centered on (0,0,0) at start. I implemented a standard trackball, based on this code. This implements rotations as small increments/transformations to the current modelview matrix,
// We need to apply the rotation as the last transformation.
// 1. Get the current matrix and save it.
// 2. Set the matrix to the identity matrix (clear it).
// 3. Apply the trackball rotation.
// 4. Pre-multiply it by the saved matrix.
glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *)objectXform);
glLoadIdentity();
glRotatef(rot_angle, rotAxis.x, rotAxis.y, rotAxis.z);
glMultMatrixf((GLfloat *)objectXform);
This part works perfectly. But then I wantes to implement translations, and I am doing this also as small increments to the modelview matrix,
glTranslatef(-dx, -dy, 0.f);
This also works as expected (no matter how the world is rotated, the translation goes along with the mouse, i.e., the model goes behind the mouse.
The problem comes when I try to rotate after the translation: I want the rotation to be around the world center, but that will not happen after user translations. I tried to store the absolute translation and compensate for it, but obviously it does not work. I did it as folows:
// Translation part, store absolute translation
m_mouseInfo.m_fTotalTranslationX -= dx;
m_mouseInfo.m_fTotalTranslationY -= dy;
glTranslatef(-dx, -dy, 0.f);
...
// Rotation, try to apply the rotation around (0,0,0)
glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *)objectXform);
glLoadIdentity();
// Try to compensate for the translation and do the rotation aroun (0,0,0) but won't work
glTranslatef(m_mouseInfo.m_fTotalTranslationX, m_mouseInfo.m_fTotalTranslationY, 0.f);
glRotatef(rot_angle, rotAxis.x, rotAxis.y, rotAxis.z);
glTranslatef(-m_mouseInfo.m_fTotalTranslationX, -m_mouseInfo.m_fTotalTranslationY, 0.f);
glMultMatrixf((GLfloat *)objectXform);
How can I store the absolute translation to compensate for it when I apply the rotation and therefore rotate the scene around the origin?
Or, in other words, how can I just rotate the world around the origin when I have cumulative transfromations?
To translate around a point (x,y), first translate by (x,y), then rotate, then translate by -(x,y).
Now, if your world has been transformed by M (some matrix), then the origin of the world before that transformation is located at M^-1 (0,0).
Suppose your world transformation from the original is M, and you want to perform some rotation R, but that rotation should be around the original origin, but the rotation matrix R is expressed in terms rotation around the point (0,0) (as is the style).
Then R' = M R M^-1 will generate a new matrix R' that consists of rotating by R around the original (0,0). Then M' = R' M is the matrix that represents starting with nothing, and then doing M, then doing R around the origin.
If you are doing cumulative transformations on some model, simply keep track of the product of said transformations, along side modifying the scene.
Alternatively, store the original scene, and instead of doing cumulative transformations on it, always apply M to get the current scene.

from glLookAt() to glRotatef() and gltranslatef

I need to replace the gluLookAt() operate by glRotatef() and glTranslatef() operations.
I mange to do that with gluLookAt(1,1,0,0,0,0,0,1,0); but I just guessed some number utill i got the same picture.
what is the math behind that? how can i take some random gluLookAt(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upZ, upY, upZ) and change it to rotate and translate and get the same picture?
gluLookAt (...) sets up the axes and origin of your view-space.
It is far easier, in my opinion, to consider what each individual column represents than to turn this operation into a series of translations and rotations (even though fundamentally that is what happens).
To setup the orientation of your view-space, gluLookAt (...) basically computes the individual axes. At no point does it ever deal with any Euler angles like glRotatef (...) would require you to do. Given the fact that the view-space gluLookAt (...) produces is orthogonal, computing the third axis from only two is trivial.
The Z-axis (forward) is computed as the direction from eyexyz to centerxyz
The Y-axis (up) is given directly as upxyz
The X-axis (right) is computed as the cross-product between the up and forward vectors
These three axes are then stored in columns 1-3 of the matrix, X, Y, Z.
Last, since the viewing transform has position in addition to rotation, the camera's eye point is stored in the 4th column of your matrix.
Consider the following diagram from Song Ho Ahn (안성호), OpenGL Transformation:
           
Honestly, it is more convenient just to setup the matrix yourself instead of dealing with Euler angles and glRotatef (...).
I agree with Andon that finding the whole matrix is much easier. But if you still need to find the decomposition to glRotate and glTranslate, then you could follow these steps, at least for this specific setting.
We need to find a transformation that would convert the representation of a point in the xyz coordinate system into its representation in the x'y'z' coordinate system (different from transforming a point). This is the same as aligning the orange system with the blue one.
We can say two things about this transformation:
The y'z'=Uz' plane is transformed into the yz plane.
The z' axis is transformed into the z axis.
To make the transformation we do the following:
Translate the origin E to point C.
Rotate around the y' axis 90° clockwise to meet condition (2).
Rotate around the z=z' axis 45° clockwise to meet condition (1).
This can be summed up as:
glRotatef(45, 0, 0, 1);
glRotatef(90, 0, 1, 0);
glTranslatef(-1, -1, 0);

Rotation and translation of the Earth opengl c++

I am trying to get a sphere to rotate around another simulating the orbit of the Earth.
I am able to get the Earth to orbit around the sun; however, I can't get it to rotate around itself.
This is the code I have so far:
//sun
glMaterialAmbientAndDiffuse(GLMaterialEnums::FRONT,GLColor<GLfloat,4>(1.5f,1.0f,0.0f));
glTranslate(0.0f, 0.0f, 0.0f);
glRotate(15.0, 1.0, 0.0, 0.0);
drawEllipsoid(10.0, 1.0, 4, 4);
glPushMatrix();
//Earth
glMaterialAmbientAndDiffuse(GLMaterialEnums::FRONT,GLColor<GLfloat,4>(0.5f,10.5f,10.5f));
glRotate(orbit,Vrui::Vector(0,0,1));
glTranslate(105.0, 0.0, 0.0);
drawPlanetGrid(5, 1, 4, 4, 1);
glPopMatrix();
orbit += .1;
if (orbit > 360)
{
orbit = 0;
}
Could anyone help me move in the right direction? I also needed to know how I can get the Earth to orbit around the sun in a tilted angle.
Basically, you need to manage some model matrices. The sun's model matrix (if centered in (0,0,0) has just a rotational part). The earth rotating around the sun, needs a model matrix which is first rotated and then translated to be placed in the orbit of the sun. So when calculating a new frame you increase your rotation parameter, create the rotation and then apply the translation. If you want to add a moon, you need another model matrix, which is accumulated. That is, the moon needs a separate rotation and translation (like the sun) but you have to account also for the transformation of the earth. Make sure that you understand what a transformation matrix does. In that case the transformation matrix is just a coordinate transformation. So, you have your sun, earth and moon in a local frame. The model matrices achieve the transformation from local coordinate system to the world coordinate system. The view matrix transforms world coordinates to eye coordinates. And then there is only projection left for you.
To solve this, you need to understand the idea of co-ordinate systems and how to use them within OpenGL.
A co-ordinate system is just a set of points that share the same XYZ axes. In each system, the XYZ axes do not necessarily point in the same direction, so in one system moving in positive X could move in negative Y in other system. To convert points from one system to another you use a transformation matrix.
A scene is made up of several co-ordinate systems:-
World space
Camera space (or view space)
Object space
Model space
So, your model (the Earth, say) has a transformation from its model space to object space - this is the rotation of the earth around the vertical axis. Then it has a transformation from object space to world space - this is the translation about the sun and tilting. The final transformation is from world space to camera space.
So, you need three matrices to put your Earth model into the right place on screen. this may seem like a lot of processing, but the thing about these matrices is that they can be multiplied together to form a single object->camera space matrix.
Once you've set up the scene using the various co-ordinate systems and transformations, it should work.
You may want to work with cubes rather than spheres to start with as it's easier to follow what is happening to the vertices as they're being transformed.

Object, world, camera and projection spaces in OpenGL

I'm trying to understand creating spaces in OpenGL:
Object space
World space
Camera space
Projection space
Is my understanding of these stages correct?
The "cube" is being created in the center of the cartesian coordinate system, directly inside the program by typing the vertices coordinates.
The coordinates are transformed into coordinates inside of the "world", which means moving it to any place on the screen.
Well, actually I'd like you to check my understanding of those two terms.
Now, I'm creating a triangle on the black screen. How does openGL code fits to these spaces?
It works on GL_MODELVIEW flag by default, but that's the second stage - world space. Does that mean that calling glVertex3f() creates a triangle in the object space?
Where is the world space part?
Also, I've read that the last two spaces are not part of the openGL pipeline (or whatever it's called).
However, OpenGL contains flags such as the GL_PROJECTION, for example:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, w, h); // w - width, h - height
gluPerspective(45, ratio, 1, 100); // radio = w/h
glMatrixMode(GL_MODELVIEW);
What does this code do? It sets the perspective. Does it create the z axis? But isn't it already the object space part?
1) Object space is the object's vertices relative to the object's origin. In the case of a 1x1x1 cube, your vertices would be:
( 0.5, 0.5, 0.5)
(-0.5, 0.5, 0.5)
( 0.5, -0.5, 0.5)
(-0.5, -0.5, 0.5)
etc.
2) World space is where the object is in your world. If you want this cube to be at (15, 10), you'd create a translation matrix that, when multiplied with each vertex, would center your vertices around (15, 10). For example, the first vertex would become (15.5, 10.5, 0.5). The matrix to go from object to world space is called the "model" matrix.
3) Eye Space (sometimes called Camera space) is the world relative to the location of the viewer. Since this has to be a matrix that each vertex is multiplied by, it's technically the inverse of the camera's orientation. That is, if you want a camera at (0, 0, -10), your "view" matrix has to be a translation of (0, 0, 10). That way all the objects in the world are forward 10 units, making it look like you are backwards 10 units.
4) Projection space is how we apply a correct perspective to a scene (assuming you're not using an orthographic projection). This is almost always represented by a frustum, and this article can explain that better than I can. Essentially you are mapping 3d space onto another skewed space.
OpenGL then handles clip space and screen space.
It works on GL_MODELVIEW flag by default, but that's the second stage - world space. Does that mean that calling glVertex3f() creates a triangle in the object space?
You set vertices with glVertex3f() in object space always. (this is actually a very old and slow way to do it, but that's not really the point of this question)
When you set GL_MODELVIEW, it's only changing the model matrix (which can be manipulated with glLoadMatrix, glTranslate, glRotate, glScale, etc.).
Line by line, your piece of code is doing the following:
All transformations will now be affecting the projection matrix.
Clear out the old projection matrix and replace it with the identity matrix.
Use the entire screen as the viewport.
Set the projection matrix to a perspective with a 45 degree vertical field of view with an aspect ratio of w/h, the near-clip plane 1 unit away, and the far-clip plane 100 units away.
All transformations are now affecting the modelview matrix again.
The Z axis already exists, this just sets the projection matrix that gives you perspective, tells OpenGL to use the entire window to render. This isn't the object space, it's the way you transform object space to projection space.
Also a side note, you're using really, really old OpenGL (1992 old). glTranslate, etc. were deprecated a long time ago and are now just removed from the API. The only reason you can still use them is because drivers keep them there for compatibility's sake. I'd recommend you look into using modern (3.0+) OpenGL. Modern graphics pipelines are several orders of magnitude faster than immediate mode (glBegin, glVertex, glEnd).

OpenGL Rotation

I'm trying to do a simple rotation in OpenGL but must be missing the point.
I'm not looking for a specific fix so much as a quick explanation or link that explains OpenGL rotation more generally.
At the moment I have code like this:
glPushMatrix();
glRotatef(90.0, 0.0, 1.0, 0.0);
glBegin(GL_TRIANGLES);
glVertex3f( 1.0, 1.0, 0.0 );
glVertex3f( 3.0, 2.0, 0.0 );
glVertex3f( 3.0, 1.0, 0.0 );
glEnd();
glPopMatrix();
But the result is not a triangle rotated 90 degrees.
Edit
Hmm thanks to Mike Haboustak - it appeared my code was calling a SetCamera function that use glOrtho. I'm too new to OpenGL to have any idea of what this meant but disabling this and rotating in the Z-axis produced the desired result.
Ensure that you're modifying the modelview matrix by putting the following before the glRotatef call:
glMatrixMode(GL_MODELVIEW);
Otherwise, you may be modifying either the projection or a texture matrix instead.
Do you get a 1 unit straight line? It seems that 90deg rot. around Y is going to have you looking at the side of a triangle with no depth.
You should try rotating around the Z axis instead and see if you get something that makes more sense.
OpenGL has two matrices related to the display of geometry, the ModelView and the Projection. Both are applied to coordinates before the data becomes visible on the screen. First the ModelView matrix is applied, transforming the data from model space into view space. Then the Projection matrix is applied with transforms the data from view space for "projection" on your 2D monitor.
ModelView is used to position multiple objects to their locations in the "world", Projection is used to position the objects onto the screen.
Your code seems fine, so I assume from reading the documentation you know what the nature of functions like glPushMatrix() is. If rotating around Z still doesn't make sense, verify that you're editing the ModelView matrix by calling glMatrixMode.
The "accepted answer" is not fully correct - rotating around the Z will not help you see this triangle unless you've done some strange things prior to this code. Removing a glOrtho(...) call might have corrected the problem in this case, but you still have a couple of other issues.
Two major problems with the code as written:
Have you positioned the camera previously? In OpenGL, the camera is located at the origin, looking down the Z axis, with positive Y as up. In this case, the triangle is being drawn in the same plane as your eye, but up and to the right. Unless you have a very strange projection matrix, you won't see it. gluLookat() is the easiest command to do this, but any command that moves the current matrix (which should be MODELVIEW) can be made to work.
You are drawing the triangle in a left handed, or clockwise method, whereas the default for OpenGL is a right handed, or counterclockwise coordinate system. This means that, if you are culling backfaces (which you are probably not, but will likely move onto as you get more advanced), you would not see the triangle as expected. To see the problem, put your right hand in front of your face and, imagining it is in the X-Y plane, move your fingers in the order you draw the vertices (1,1) to (3,2) to (3,1). When you do this, your thumb is facing away from your face, meaning you are looking at the back side of the triangle. You need to get into the habit of drawing faces in a right handed method, since that is the common way it is done in OpenGL.
The best thing I can recommend is to use the NeHe tutorials - http://nehe.gamedev.net/. They begin by showing you how to set up OpenGL in several systems, move onto drawing triangles, and continue slowly and surely to more advanced topics. They are very easy to follow.
Regarding Projection matrix, you can find a good source to start with here:
http://msdn.microsoft.com/en-us/library/bb147302(VS.85).aspx
It explains a bit about how to construct one type of projection matrix. Orthographic projection is the very basic/primitive form of such a matrix and basically what is does is taking 2 of the 3 axes coordinates and project them to the screen (you can still flip axes and scale them but there is no warp or perspective effect).
transformation of matrices is most likely one of the most important things when rendering in 3D and basically involves 3 matrix stages:
Transform1 = Object coordinates system to World (for example - object rotation and scale)
Transform2 = World coordinates system to Camera (placing the object in the right place)
Transform3 = Camera coordinates system to Screen space (projecting to screen)
Usually the 3 matrix multiplication result is referred to as the WorldViewProjection matrix (if you ever bump into this term), since it transforms the coordinates from Model space through World, then to Camera and finally to the screen representation.
Have fun