I have the following code.
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(eyeX+eyePos, eyeY, eyeZ, lookatX+eyePos, lookatY, lookatZ, upX, upY, upZ);
glGetDoublev(GL_MODELVIEW_MATRIX,lookatMatrix);
glPushMatrix();
So we have a matrix after gluLookAt, and I presume it stores on top of current matrix mode stack. Now, we get the value out of it using GetDoulev, Then why do use glPushMatrix in the end?
glPushMatrix keeps a copy around so that you can do further manipulations on the matrix stack yet are able to easily revert to a previous state using glPopMatrix.
But truth be told, don't use it. The matrix stack has been removed from modern OpenGL and it's far more convenient to use a real matrix math library, like GLM, than doing awkward things with the OpenGL matrix stack. The moment you use glGetDoublev(GL_…_MATRIX, …) so that you can do further things with said matrix, you're doing something wrong.
Just use a real matrix math library and load whatever matrix you need at the moment using glLoadMatrix (if you absolutely have to use the old style fixed function pipeline) or load it into a shader uniform (which is what you should absolutely do whenever you can use modern OpenGL).
Related
I am trying to rotate over the 'x' axis and save the transformed matrix so that I can use it to rotate further later; or over another axis from the already rotated perspective.
//rotate
glRotatef(yROT,model[0],model[4],model[8]);//front over right axis
//save model
glGetFloatv(GL_MODELVIEW_MATRIX, model);
Unfortunately I noticed that openGL must buffer the transformations because the identity matrix is loaded to model. Is there a work-around?
Why, oh God, would you do this?
I have been toying around with attempting to understand quaternions, euler, or axis rotation. The concepts are not difficult but I have been having trouble with the math even after looking at examples *edit[and most of the open classes I have found either are not well documented for simpleton users or have restrictions on movement].
I decided to find a way to cheat.
edit*
By 'further later' I mean in the next loop of code. In other words, yRot is the number of degrees I want my view to rotate from the saved perspective.
My suggestion: Don't bother with glRotate at all, they were never very pleasant to work with in the first place and no serious program did use them ever.
If you want to use the fixed function pipeline (= no shaders), use glLoadMatrix to load whatever transformation you currently need. With shaders you have to do the conceptually same with glUniform anyway.
Use a existing matrix math library, like GLM, Eigen or linmath.h to construct the transformation matrices. The nice benefit is, that you can make copies of a matrix at any point, so instead of fiddling with glLoadIdentity, glPushMatrix and glPopMatrix you just make copies where you need them and work from them.
BTW: There is no such thing as "models" in OpenGL. That's not how OpenGL works. OpenGL draws points, lines or triangles, one at a time, where each such called primitive is transformed individually to a position on the (screen) framebuffer and turned into pixels. Once a primitive has been processed OpenGL already forgot about it.
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.
I don't know the right term to describe it that is why I can't find it in Google. All I want is to scale the object, specifically, 2D rectangle but keep it on its XY coordinates.
My current solution is this:
glTranslatef(x, y, 0);
glScalef(scaleX, scaleY, 0);
glTranslatef(-x, -y, 0);
drawRect(x, y, width, height, texture);
I just pretend glScale as glRotate as of rotating on its center, it somewhat work but I can see the little adjustments on its coordinate when scaling to other value.
And also, which is better to do, glTranslate or just apply variables such as x,y on vertices. I can't see no difference when switching from those two but I am worrying about adding the "pushing and popping matrices" will affect the behavior of other objects on the scene and performance of my program, because I will use lots of this rectangles.
Update:
So you can visualize how simply I want to achieve
I suppose that <x,y,0> is the position of the bottom left corner of your rectangle in the "canonical" coordinate system (I mean the one we start with).
With these assumptions, you may achieve your goal by resetting the modelview stack to identity, and then move to the object space, before doing the scaling. So you are indeed pretty close, but depending on what you did before with the modelview matrix, you could experience variations in the outcome.
The following code should do what you want:
glPushMatrix();
glLoadIdentity();
glTranslatef(x, y, 0);
// now in "object space"
glScalef(scaleX, scaleY, 0);
drawRect(0, 0, width, height, texture);
glPopMatrix();
I don't know what the draw function does, but I suppose that it just emits a bunch of glVertex and glTexCoord calls, ie. it does not meddle with the modelview matrix, otherwise my code might well break it.
Note that if you wrap all object rendering with glPushMatrix and glPopMatrix calls, you should not need the glLoadIdentity call, and it might even be counter productive. For instance, if you organize your object data as a hierarchy, with each sub object being relatively positioned to its container, then you will need to remove that call completely while recursively rendering the object hierarchy.
Another concern is the one of efficiency. Saving and restoring matrices are fairly costly operations. Given that your question code is using immediate mode, I supposed that it was not your main concern. It will certainly be faster to apply the object transformation by hand (that is, by computing them with your own matrix library), and submit them to opengl without any call to the opengl modelview manipulation routines. However That should be covered by another (more math oriented) question and answer.
The general pattern for a rotation by angle phi (applies to other affine transformations as well) that keeps the point (x,y) fixed is
TRANSLATE(-x, -y)
ROTATE(phi)
TRANSLATE(x, y)
Transformations are applied in order from top to bottom. So you're moving the point (x,y) into the origin at (0,0). It will thus not be affected by the actual rotation. When you're done, the second translation reverses the effect of the first.
This is not limited to OpenGL, but rather applies to any type of graphics processing that supports affine transformations (through matrices or quaternions).
Suppose I have the following code:
glRotatef(angle, 1.0f, 1.0f, 0.0f);
glRotatef(angle, 0.0f, 1.0f, 0.0f);
glRotatef(angle, 0.0f, 0.0f, 1.0f);
glTranslatef(0.0f, 0.0f -5.0f);
Is this less efficient than utilizing one's own custom matrix via the glLoadMatrix function that accomplishes the same functionality?
Also, I know that when multiplying matrices to form a custom linear transformation, the last matrix multiplied is the first transformation to take place. Likewise, is this the case if I utilize the above code? Will it translate, then rotate about the Z axis, followed by rotations about the y and x axes?
In general if you assemble your matrix on your own and load it via glLoadMatrix or glMultMatrix your program will run faster. Unless you make stupid mistakes in your own matrix routines that ruin the performance of course.
This is because the glRotate glTranslate etc. functions do quite a bit more than the pure math. They have to check the matrix-mode. glRotate has to deal with cases where the axis is not passed as a unit-vector etc.
But unless you do this 10thousands times per frame I wouldn't worry about the lost performance. It adds up, but it's not that much.
My personal way of dealing with openGL transformations is to build the matrices in my code and only upload them to OpenGL via glLoadMatrix. This allows me to do lots of shortcuts like reversing the order of multiplications (faster to calculate than the way OpenGL does it). Also it gives me instant access to the matrix which is required if you want to do boundary box checks before rendering.
Needless to say code written with such an approach is also easier to port onto a different graphics API (think OpenGL|ES2, DirectX, Game-Consoles...)
According to the OpenGL specs the glRotate and glTranslate are using their parameters to produce a 4x4 matrix, then the current matrix is multiplied by the (glRotate or glTranslate) produced matrix with the product replacing the current matrix.
This roughly means that in your enlisted code you have 4 matrix multiplications! On top of that you have 4 API calls and a few other calculations that convert the angles of glRotate to a 4x4 matrix.
By using glLoadMatrix you will have to produce the transformation matrix yourself. Having the angles and the translation there are way more efficient ways to produce that transformation matrix and thus speedup the whole thing.
Is this less efficient than utilizing one's own custom matrix via the glLoadMatrix function that accomplishes the same functionality?
Very likely. However if you're running into a situation where setting of the transformation matrices has become a bottleneck you're doing something fundamentally wrong. In a sanely written realtime graphics program calculation of the transformation matrices should make only a very small amount of the things processed in total.
A example for very bad programming was something like this (pseudocode):
glMatrixMode(GL_MODELVIEW)
for q in quads:
glPushMatrix()
glTranslatef(q.x, q.y, q.z)
glBindTexture(GL_TEXTURE_2D, q.texture)
glBegin(GL_QUADS)
for v in [(0,0), (1,0), (1,1), (0,1)]:
glVertex2f(v[0], v[1]
glEnd()
glPopMatrix()
Code like this will perform very poorly. First you're spending an awful lot of time in calculating the new transformation matrix for each quad, then you restart a primitive batch for each quad, the texture switches kill the caches and last but not least its using immediate mode. Indeed the above code is the the worst of all OpenGL anti-patterns in one single example.
Your best bet for increasing rendering performance is to avoid any of the patterns you can see in above example.
Those matrix functions are implemented in the driver, so they might be optimized. You will have to spend some time to write your own code and test if the performance is better or not than the original OpenGL code.
On the other hand in "new" version of OpenGL all of those functions are missing and marked as deprecated. So in new standard you are forced to use custom math functions (assuming that you are using Core profile)
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();