I am playing with opnegl (the old one, sorry for the modern opengl guys), and I'm trying to understand the matrixes and replace glRotatef, glTranslatef etc with glLoadMatrixf.
I don't understand how to set a matrix with no rotation, no translation, no scale. I thought I could use an identity matrix but it doesn't work.
I'd like to have a matrix such that writing:
glPushMatrix();
{
drawMyCube();
}
glPopMatrix();
is the equivalent to writing:
glPushMatrix();
{
glLoadMatrixf( myCubeTransform.getTranspose() );
drawMyCube();
}
glPopMatrix();
If I have something like:
/* 1: */ // glLoadMatrixf( myCubeTransform.getTranspose() );
/* 2: */ // glLoadIdentity();
In the first place I thought to use myCubeTranform Matrix4 class (and I'm using a row-major order matrix class so I have to getTranspose() to match opengl column-major order) but it doesn't work, so I used glLoadIdentity to be sure to does not make mess with my Matrix4 class (some bug in matrix code?) and.. it doesn't work either.
So my question: how to set a transform matrix with no translation, no rotation, no scale?
With "does not work" I mean that my cube is not in the origin (where I want it to be). Actually, I don't see it at all (prob. it is drawn outside the view frustum?)
glLoadMatrix will replace what's on top of the matrix stack. Which means, that it will nil your view setup, that you probably did before. You have to choices: Either implement the view part yourself as well and pre-multiply that on the model transformation. Or (for learning purposes) use glMultMatrix instead of where you have glLoadMatrix right now.
Related
I have written this piece of code in c to draw a planet system with a sun and a planet
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0,0.0,0.0);
glMatrixMode(GL_MODELVIEW_MATRIX);
glPushMatrix();
glutWireSphere(1.0, 20, 16);
glLoadIdentity();
glRotatef((GLfloat) year ,0.0,1.0,0.0);
glTranslatef(2.0, 0.0, 0.0);
glRotatef((GLfloat) day, 0.0, 1.0, 0.0);
glutWireSphere(0.2, 10, 8);
glPopMatrix();
glutSwapBuffers();
But when I compile and run the code, second sphere is not in the view. After I increase the value of y, it appears for half of the rotation when it is behind the centre sphere and then goes out of View again, also the size of the sphere is larger than expected. if I comment out the call to glLoadIdentity(), everything works fine. As much as I know, glLoadIdentity() loads the current Matrix(ModelView_Matrix) with an identity matrix so that the effect of all the translations and rotations is reversed but why in this case the objects drawn when its called are in different manner when no rotations or transformations are being performed before its call?
I suspect that you do have other transformations in the ModelView matrix. If it was already set to the identity, then loading identity would not change the behaviour.
The code you have provided only sets up a local model transform. There are no projection or view transformations being applied, so these must be done elsewhere. Perhaps at initialisation.
Without a prior view transformation, the first sphere would be drawn at the same position as the view - in other words, the camera would be inside the sphere.
I suspect your problem is related to the way you make use of glPushMatrix and glPopMatrix in conjunction with glLoadIdentity:
Suppose you have some matrix A on your modelview stack. Now you use glPushMatrix, essentially saving A to restore it later. Inside the push-pop block, you tell GLUT to draw a sphere, which it dutyfully does, using the previously mentioned modelview matrix A.
If you now call glLoadIdentity, anything that A was before, is gone until you call glPopMatrix, which restores the previous state of A.
So in short, transformation calls after glLoadIdentity are based on the identity matrix rather than the matrix state previous to glPushMatrix.
Seeing that what you want to do is drawing a solar system. It'd probably be best to do something like:
glPushMatrix();
/* Transformations positioning the sun */
/* Draw the sun */
glPushMatrix();
/* Transformations for getting from the sun to the planet */
/* Draw the planet */
glPopMatrix();
glPopMatrix();
As an aside, the fixed-function pipeline (glTranslate, glRotate, glPushMatrix, ...) has been deprecated for quite a while now (about 10 years?), so I'd suggest picking up OpenGL using a more modern approach.
Edit:
While re-reading the question, another thing struck my attention:
Assuming year is designating where the planet is in its revolution around the sun and day specifies how much the plant is rotated around its own polar axis, the correct order of transformations would be:
Rotate by day around the y-axis
Translate
Rotate by year around the y-axis
(Right now, you're doing it the opposite way, which could explain the strange behaviour you're experiencing. See also here.)
According to the comment by JasonD, your transformation order was right in the first place, but still it won't hurt to know about the background. ;)
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
//set viewpoint
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(VIEW_ANGLE,Screen_Ratio,NEAR_CLIP,FAR_CLIP);
gluLookAt(0,5,5, 0,0,0, 0,1,0);
//transform model 1
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(Theta, 0,1,0);
//draw model 1
glBegin(GL_QUADS);
...
glEnd();
The code above works fine, but is there any way to remove the call to gluPerspective?
What I mean is, I would like to call it only once in initialization, instead of repeatedly during each rendering.
You call gluPerspective there, because it belongs there. OpenGL is not a scene graph where you initialize things. It's a state driven drawing API. The projection matrix is a state and every serious graphics application changes this state multiple times throughout a single frame rendering.
OpenGL does not know geometrical objects, positions and cameras. It just pushes points, lines and triangles through a processing pipeline, and draws the result to the screen. After something has been drawn, OpenGL has no recollection of it, whatsoever.
I mean calling it only once in initialization.
OpenGL is not initialized (except creation of the rendering context, but actually this is part of the operating system's graphics stack, not OpenGL). Sure, you upload textures and buffer object data to it, but that can happen anytime.
Do not use gluLookAt on the projection matrix, as it defines the camera/view and therefore belongs to the modelview matrix, usually as the left-most transformation (the first after glLoadIdentity), where it makes up the view part of the word modelview. Although it also works your way, it's conceptually wrong. This would also solve your issue, as then you just don't have to touch the projection matrix every frame.
But actually datenwolf's approach is more conceptually clean regarding OpenGL's state machine architecture.
If you don't call glLoadIdentity() (which resets the current matrix to be the identity matrix, i.e. undoes what gluPerspective() has done) every frame and instead carefully push/pop the transform matrices you can get away with calling it only in initialization quite happily. Usually it's far easier just to call load identity each time your start drawing and then reset it. e.g.:
// Initalisation
glLoadIdentity();
gluPerspective(...);
Then later on:
// Drawing each frame
glClear(...);
glPushMatrix();
gluLookAt(...);
//draw stuff
glPopMatrix();
I'm writing an 3D Scanner with a Kinect and i want to display the Point clouds..
The Pointclouds have an additional Transformmatrix from a Trackingsystem..
I use:
scale = 0.0005;
glScaled(scale, scale, scale);
to encounter the Problem, that x,y,z Value ranges from 0 - 10.000 are cut by Opengl due to clipping planes.
when i use glLoadMatrix(trackingtransform); i don't see anything.. even if i use glscale again after the loadmatrix.
glLoadMatrix replaces the matrix that you generated with glScaled.
if you want to combine them, use glMultMatrix instead of glLoadMatrix.
That said, I'd advise to do what datenwolf alludes to. Use the projection matrix to set a coordinate system that maps your usage scenario (i.e. a world in the 0-10000 range), and keep the modelview matrix to move around.
You can directly scale the matrix your points are in, like:
glPushMatrix();
glScale();
-draw all your points...
glPopMatrix();
I have my object's rotation and translation in a quaternion, which I've converted to a matrix[16].
How do I feed that matrix to OpenGL? I'd-a thought I could just glLoadMatrix() with my new, fancy-pants matrix and all would be good, but I'm getting a blank screen.
(I'm a bit of a GL n00b, so type slowly and use small words ;)
My code looks something like this:
glPushMatrix();
[quaternion makeIdentity]; // reset quat
[quaternion setPitch: rotation.x yaw: rotation.y roll: rotation.z]; // Set up with rotation coords (NOTE: setPitch:yaw:roll: is smart about degrees->radians)
GLdouble matrix[16];
[quaternion matrix: &matrix[0]]; // get quat -> matrix
matrix[12] = location.x; // fill in the translation
matrix[13] = location.y;
matrix[14] = location.z;
glLoadMatrixd(matrix);
glScaled(scale.x, scale.y, scale.z);
// draw geometry here -- snip
glPopMatrix();
I think I'm pretty close but, when I use this code, I get a blank display (everything is glClearColor.)
NOTE: when I skip the quaternion part and do something like this:
glPushMatrix();
glTranslatef(location.x, location.y, location.z);
glRotated(rotation.z, 0, 0, 1.0);
glRotated(rotation.x, 1.0, 0, 0);
glRotated(rotation.y, 0, 1.0, 0);
// draw geometry here -- snip
glPopMatrix();
the display is as expected. The only problem is that my rotations are screwy, due to being applied sequentially. Hence my desire to use quaternions.
If you don't forgot to set current matrix mode to GL_MODELVIEW, your matrix should be loaded correctly. Check your quat -> matrix calculations. I'd start from rotation by zero angle and comparing result with identity matrix.
Quaternions don't have a translation part. The translation must be maintained separately, as is the case in the second code snippet.
I'm not sure the code will do what's desired, anyway. Quaternions won't solve gimbal lock, if the problem is being stated in the very way that introduces gimbal lock in the first place. If the quaternion is being set afresh from pitch/yaw/roll each frame, there will be the same problems as before, and for the same reasons. (And if it appears that's not the case, that's because the quaternion construction code is doing the same thing that the matrix construction code could do, but in this case doesn't: rotating about each rotated axis in turn, rather than rotating about a fixed one.)
To fix this, maintain a quaternion as part of the object's state, and apply each rotation to it directly. This doesn't really buy one much that couldn't be done just as easily with a matrix, though. (I haven't counted the operations, so that's not so say that it may turn out to be rather more efficient one way rather than the other.)
The main advantage of quaternions is that it's easy to interpolate between them, getting something reasonable at each intermediate step, simply by summing the weighted inputs and normalizing the result. SLERP is also an option. The equivalent operation on matrices comes unstuck in certain situations (e.g., with two matrices representing opposing orientations, you'll end up with a column consisting entirely of zeros...), and trying to do something similar with pitch/yaw/roll just generates a big mess.
As for turning one into a matrix, if you've got a quaternion whose vector part is (qx,qy,qz) and whose scalar part is qw, you can turn it into an OpenGL matrix using code like this:
mtx[0]=1.f-2.f*qy*qy-2.f*qz*qz;
mtx[1]=0.f+2.f*qx*qy+2.f*qw*qz;
mtx[2]=0.f+2.f*qx*qz-2.f*qw*qy;
mtx[3]=0.f;
mtx[4]=0.f+2.f*qx*qy-2.f*qw*qz;
mtx[5]=1.f-2.f*qx*qx-2.f*qz*qz;
mtx[6]=0.f+2.f*qy*qz+2.f*qw*qx;
mtx[7]=0.f;
mtx[8]=0.f+2.f*qx*qz+2.f*qw*qy;
mtx[9]=0.f+2.f*qy*qz-2.f*qw*qx;
mtx[10]=1.f-2.f*qx*qx-2.f*qy*qy;
mtx[11]=0.f;
mtx[12]=0.f;
mtx[13]=0.f;
mtx[14]=0.f;
mtx[15]=1.f;
The above was search-and-replace-ed into the above form, so I really hope I didn't screw it up.
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