I'm currently trying to get to know the basics with the means of OpenGL.
At the time I try to render a Floating Cube with a Pyramid beneath it. I want the Cube to rotate on Input (which is already working) and the Pyramid to stay where it's supposed to be.
After figuring out the use of Push- and PopMatrix I managed to rotate only the cube.
My Problem is, that the Cube stops rotating as soon as I let go of the key.
The player.X and Player.Z aren't reset at that point (checked that).
So my guess is that PushMatrix puts some kind of standard matrix onto the stack, then rotates it and displays it. Because of 1 * x always equalling x there is no rotation.
So the question is:
How do I manage to push the "old" matrix onto the stack, rather than the new one?
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glPushMatrix();
glRotatef( -(player->Z), 1.0f, 0.0f, 0.0f );
glRotatef( -(player->X), 0.0f, 1.0f, 0.0f );
glBegin( GL_QUADS );
//Draw Cube
glEnd();
glPopMatrix( );
glBegin( GL_TRIANGLES );
//Draw Pyramid
glEnd();
glFlush();
SwapBuffers (hDC);
glPushMatrix() does not push a 'standard' matrix onto the stack, it pushes the current matrix. Hopefully you've initialised the matrix at some point with a glLoadIdentity(), and possibly some initial transforms to set up the view, and so this is what will be pushed.
You should not generally keep updating that matrix from frame to frame, as errors will eventually accumulate.
Instead, update your rotation values in some update loop, rather than in the key-down routine.
Also, note that this method of rendering with GL is considered deprecated. The recommended approach is to use the programmable pipeline, which involves creating your own matrices (amongst other changes).
(if you desperately want to keep a persistent transform while also pushing and popping to render other things, it is possible to read the current matrix with a glGet(), store it somewhere, and then perform a glLoadMatrix() to restore it again later... but don't do that for this.)
Related
I am doing in a simplistic experiment as below:
glPushMatrix();
glGetDoublev(GL_MODELVIEW, modelMatrix);
glTranslatef(...);
glGetDoublev(GL_MODELVIEW, modelMatrix);
glPopMatrix();
However, after the translation, there is not change in the modelview matrix. I am wondering why is that, and how can I see the effect of this translation? In other words, how can I get the transformation marix?
Your code is invalid. The correct enum for glGet...() is GL_MODELVIEW_MATRIX, not GL_MODELVIEW (which is a constant for use glMatrixMode()), so all you get is some GL error, and the memory at modelMatrix will be not touched at all, so it is probably just left uninitialized.
I am creating a 3D graphics engine and one of the requirements is ropes that behave like in Valve's source engine.
So in the source engine, a section of rope is a quad that rotates along it's direction axis to face the camera, so if the section of rope is in the +Z direction, it will rotate along the Z axis so it's face is facing the camera's centre position.
At the moment, I have the sections of ropes defined, so I can have a nice curved rope, but now I'm trying to construct the matrix that will rotate it along it's direction vector.
I already have a matrix for rendering billboard sprites based on this billboarding technique:
Constructing a Billboard Matrix
And at the moment I've been trying to retool it so that Right, Up, Forward vector match the rope segment's direction vector.
My rope is made up of multiple sections, each section is a rectangle made up of two triangles, as I said above, I can get the position and sections perfect, it's the rotating to face the camera that's causing me a lot of problems.
This is in OpenGL ES2 and written in C.
I have studied Doom 3's beam rendering code in Model_beam.cpp, the method used there is to calculate the offset based on normals rather than using matrices, so I have created a similar technique in my C code and it sort of works, at least it, works as much as I need it to right now.
So for those who are also trying to figure this one out, use the cross-product of the mid-point of the rope against the camera position, normalise that and then multiply it to how wide you want the rope to be, then when constructing the vertices, offset each vertex in either + or - direction of the resulting vector.
Further help would be great though as this is not perfect!
Thank you
Check out this related stackoverflow post on billboards in OpenGL It cites a lighthouse3d tutorial that is a pretty good read. Here are the salient points of the technique:
void billboardCylindricalBegin(
float camX, float camY, float camZ,
float objPosX, float objPosY, float objPosZ) {
float lookAt[3],objToCamProj[3],upAux[3];
float modelview[16],angleCosine;
glPushMatrix();
// objToCamProj is the vector in world coordinates from the
// local origin to the camera projected in the XZ plane
objToCamProj[0] = camX - objPosX ;
objToCamProj[1] = 0;
objToCamProj[2] = camZ - objPosZ ;
// This is the original lookAt vector for the object
// in world coordinates
lookAt[0] = 0;
lookAt[1] = 0;
lookAt[2] = 1;
// normalize both vectors to get the cosine directly afterwards
mathsNormalize(objToCamProj);
// easy fix to determine wether the angle is negative or positive
// for positive angles upAux will be a vector pointing in the
// positive y direction, otherwise upAux will point downwards
// effectively reversing the rotation.
mathsCrossProduct(upAux,lookAt,objToCamProj);
// compute the angle
angleCosine = mathsInnerProduct(lookAt,objToCamProj);
// perform the rotation. The if statement is used for stability reasons
// if the lookAt and objToCamProj vectors are too close together then
// |angleCosine| could be bigger than 1 due to lack of precision
if ((angleCosine < 0.99990) && (angleCosine > -0.9999))
glRotatef(acos(angleCosine)*180/3.14,upAux[0], upAux[1], upAux[2]);
}
(Using OpenGL, GLUT, GLU, and C)
I am trying to create a 3D game in C, and I have the camera movement, collision detection and all of the main stuff ready, however I have failed at the first hurdle. To create my rectangles I am using
glutSolidCube (2.0);
And I know about tranformations and scale and rotations, however I am looking for how to place it in a precise location. Say I had a 3D space, with XYZ. Say I had the camera at 5,5,20, looking towards 0,0,0 (So at an angle) and wanted to place a Cube at 5,2,10, and then another at -5,-2,20. How would I use these absolute positions? Also, how would I use absolute sizes, so say I wanted the one at -5,-2,20 to be 20,5,10 in size. How would I do this in OpenGL?
You'll have to use the functions:
glTranslatef()
glRotatef()
glScalef()
Additionally, also learn these:
glPushMatrix()
glPopMatrix()
Read the OpenGL reference for details.
First forget about glutSolidCube. GLUT is not a part of OpenGL, it's just a small convenience library for it.
You must understand the OpenGL only deals with points, lines and tranangles. And it doesn't maintain a scene, but its merely drawing points, lines and triangles. Each on its own without any connotation of topology. Also OpenGL should not be confused for some math library. The functions glTranslate, glRotate, glScale and so on are a pure legacy and have been removed from contemporary OpenGL versions.
That being said...
Say I had the camera at 5,5,20, looking towards 0,0,0 (So at an angle) and wanted to place a Cube at 5,2,10, and then another at -5,-2,20. How would I use these absolute positions? Also, how would I use absolute sizes, so say I wanted the one at -5,-2,20 to be 20,5,10 in size. How would I do this in OpenGL?
I'll go along with what you already know (which mans old OpenGL-1.1 and GLUT):
void draw()
{
/* Viewport and projection really should be set in the
drawing handler. They don't belong into the reshape. */
glViewport(...);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
your_projection();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(5, 5, 20, 0, 0, 0, 0, 1, 0);
glPushMatrix();
glTranslatef(5, 2, 10);
draw_cube();
glPopMatrix();
glPushMatrix();
glTranslatef(-5, -2, 20);
draw_cube();
glPopMatrix();
glPushMatrix();
glTranslatef(-5, -2, 20);
glScalef(20, 5, 10);
draw_cube();
glPopMatrix();
}
I am reading a book on OpenGL, SDL, and have read some of the OpenGL documentation. I have also read this post: What does glLoadIdentity() do in OpenGL?
I am grasping what glLoadIdentity() does, and why it is used in a general sense (to return the current matrix back to its original state). What I do not know is why I am returning it to its original state. For instance:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0f, 640, 480, 0.0f, -1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
I am not exactly sure why glLoadIdentity() has to be called after each call to glMatrixMode.
When to call glMatrixMode() -- 1st answer tries to explain:
glLoadIdentity() is typically called immediately after a matrix mode change so you are starting "fresh" if you will. Matrix transforms such as the gluPerspective(), glOrtho(), glFrustum(), glRotate(), glMultMatrix(), glTranslate() are cumulative operations because they aggregate to allow you to describe complex 3D world space transforms or to describe your OpenGL viewing volume. Example: if I want a cube translated in the +X direction then rotated around the Z axis I issue a glRotate() followed by a glTranslate().
glLoadIdentity() wipes out the matrix (of the current matrix mode) with the identity matrix so following a gluPerspective() by glLoadIdentity() is equivalent to a single call to glLoadIdentity(). In other words, that sequence is nonsensical.
I've been trying to get a HUD texture to display for a simulator for a while now, without success.
First I bind the texture like this:
glGenTextures(1,&hudTexObj);
gHud = getPPM("textures/purplenebula/hud.ppm",&n,&m,&s);
glBindTexture(GL_TEXTURE_2D,hudTexObj);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
//glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,n,m,0,GL_RGB,GL_UNSIGNED_INT, gHud);
And then I attempt to map it to a QUAD, which results in the whole quad being a single brown color, and I want it to use all the texels. Here's how I map:
glBindTexture(GL_TEXTURE_2D,hudTexObj);
glBegin(GL_QUADS);
glTexCoord2f(0.0,0.0);
glVertex2f(0,0);
glTexCoord2f(0.0,1.0);
glVertex2f(0,m);
glTexCoord2f(1.0,1.0);
glVertex2f(n,m);
glTexCoord2f(1.0,0.0);
glVertex2f(n,0);
glEnd();
The weird thing is that I've been able to get the exact above code to display the texture in a program of its own, yet when I put it into my main program it fails. Could it have to do with the texture matrix? I'm dumbfounded at this point.
Stupidly, I had enabled automatic tex coord generation far away in another part of the code. So if you see one texel's color covering a whole image, that is the likely cause.