I am currently working on the printing loop of my software that reads 3D obj file.
I have stored my obj file read in the variable tie. This variable contain an OpenGL list. My objective is to be able to move around the read object by using keyboard. The keyboard reading is implemented correctly (i can see in through the logs).
Issue
When i compile the following code loop, the gluLookAt exucute properly and I am able to move around my object by changing the value of the parameters.
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) ;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
light();
gluPerspective (60.0, 250/(float)250, 0.1, 500.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(eyeX,eyeY,eyeZ,eyeX+directionX,eyeY+directionY,eyeZ+directionZ,upX,upY,upZ);
glPushMatrix();
glRotated(45,0,0,1);
glTranslated(0,0,50);
glBindTexture(GL_TEXTURE_2D,texture1);
//glCallList(xwing); //ICI
glEnd();
glPopMatrix();
glColor3d(1,1,1);
glDisable(GL_LIGHTING);
glBindTexture(GL_TEXTURE_2D,texture2);
GLUquadric* params = gluNewQuadric();
gluQuadricDrawStyle(params,GLU_FILL);
gluQuadricTexture(params,GL_TRUE);
gluSphere(params,100,20,20);
gluDeleteQuadric(params);
glEnable(GL_LIGHTING);
glBindTexture(GL_TEXTURE_2D,texture1);
glCallList(tie); //ICI
glPointSize(5.0);
glBegin(GL_POINTS);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f(-1.0f,0.0f,0.0f);
glEnd();
SwapBuffers(hDC);
//} //else
Sleep(1);
But when i comment these 4 lines:
glBegin(GL_POINTS);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f(-1.0f,0.0f,0.0f);
glEnd();
My object doesn't move anymore. As if gluLookAt didn't succeed to execute.
Do you have any idea why is this happening. Did I forget something in my code?
glBegin and glEnd delimit the vertices that define a primitive or a group of like primitives. You have to ensure, the each glBegin is followed by a glEnd.
This means, if your Display Lists contains a glBegin then it should contain a glEnd, too. I strongly recommend to do it this way. The other possibility would be to do it manually after glCallList:
glCallList(tie);
glEnd();
glPushMatrix and glPopMatrix are used to push matrices on and pop matrices from the matrix stack. If you want to add a model matrix to the view matrix, then you have to do the following steps.
Push the view matrix glPushMatrix. This pushs a copy of the view matrix on the stack.
Add the model matrix to the current view matrix (glRotated, glTranslated, ... )
Draw the model. (glCallList, gluSphere, ... )
Restore the original view matrix (glPopMatrix).
Adapt your code somehow like this:
// set up view matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(eyeX,eyeY,eyeZ,eyeX+directionX,eyeY+directionY,eyeZ+directionZ,upX,upY,upZ);
// save view matrix
glPushMatrix();
// add model matrix
glRotated(45,0,0,1);
glTranslated(0,0,50);
// do the drawing
glColor3d(1,1,1);
glDisable(GL_LIGHTING);
glBindTexture(GL_TEXTURE_2D,texture2);
GLUquadric* params = gluNewQuadric();
gluQuadricDrawStyle(params,GLU_FILL);
gluQuadricTexture(params,GL_TRUE);
gluSphere(params,100,20,20);
gluDeleteQuadric(params);
glEnable(GL_LIGHTING);
glBindTexture(GL_TEXTURE_2D,texture1);
glCallList(tie);
glEnd(); // <-- maybe this could be done in "tie"
// restore the view matrix
glPopMatrix();
Related
So, I've been trying to rotate a single object in an OpenGL/GLUT environment.
After going through several questions on SO and the like, I've written what appears to be correct code, but no dice. Does anyone know how to make this work?
PS: I've tried changing the GLMatrixmode to Projection, but that just shows a black screen. Same thing happens if I use glLoadIdentity().
Here's my rendering code
void display()
{
preProcessEvents();
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(Camera::position.x, Camera::position.y, Camera::position.z,
Camera::position.x+Math::sind(Camera::rotationAngles.x)*Math::cosd(Camera::rotationAngles.y),
Camera::position.y+Math::cosd(Camera::rotationAngles.x),
Camera::position.z+Math::sind(Camera::rotationAngles.x)*Math::sind(Camera::rotationAngles.y),
0.0, 1.0, 0.0);
glBegin(GL_TRIANGLES);
glColor3f(1, 0, 0);
glVertex3f(-1, 0,-3);
glColor3f(0, 1, 0);
glVertex3f(0.0f, 2.0f,-3);
glColor3f(0, 0, 1);
glVertex3f(1.0f, 0.0f,-3);
glEnd();
glBindTexture(GL_TEXTURE_2D, tex->textureID);
glBegin(GL_QUADS);
glColor3f(1, 1, 1);
glTexCoord2f(100, 100);
glVertex3f(100,0,100);
glTexCoord2f(-100, 100);
glVertex3f(-100,0,100);
glTexCoord2f(-100,-100);
glVertex3f(-100,0,-100);
glTexCoord2f(100,-100);
glVertex3f(100,0,-100);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
object1.draw();
glTranslatef(-10.0, 10.0, 0.0);
glBindTexture(GL_TEXTURE_2D, tex2->textureID);
gluQuadricTexture(quad,1);
gluSphere(quad,10,20,20);
glBindTexture(GL_TEXTURE_2D, 0);
//RELEVANT CODE STARTS HERE
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
glRotatef(190, 0.0, 0.0, 1.0);
glPopMatrix();
glutSwapBuffers();
}
Are you aware what glPushMatrix and glPopMatrix do? They save and restore the "current" matrix.
By enclosing your rotation in that and then doing no actual drawing operation before restoring the matrix the entire sequence of code beginning with //RELEVANT CODE STARTS HERE is completely pointless.
Even if you did not push/pop, your rotation would only be applied the next time you draw something. Logically you might think that would mean the next time you call display (...), but one of the first things you do in display (...) is replace the current matrix with an identity matrix (line 3).
In all honesty, you should consider abandoning whatever resource you are currently using to learn OpenGL. You are using deprecated functionality and missing a few fundamentals. A good OpenGL 3.0 tutorial will usually touch on the basics of transformation matrices.
As for why changing the matrix mode to projection produces a black screen, that is because the next time you call display (...), gluLookAt operates on the projection matrix. In effect, you wind up applying the camera transformation twice. You should really add glMatrixMode (GL_MODELVIEW) to the beginning of display (...) to avoid this.
You do the rotation (and reset it with glPopMatrix) after you draw, do the rotation code before the glBegin/glEnd calls.
Or just move to the shader based pipeline and manage you own transformation matrices.
In my openGL program using freeglut the screen is completely whited out by this code:
glBegin(GL_QUADS);
glPushMatrix();
glVertex3f(trackRadius*cos((double)x), trackHeight*sin(trackNumberOfHills*x), trackRadius*sin(x));
glVertex3f((trackRadius+1)*cos((double)x), trackHeight*sin(trackNumberOfHills*x), (trackRadius+1)*sin(x));
glVertex3f(trackRadius*cos((double)x+(0.005)), trackHeight*sin(trackNumberOfHills*(x+0.005)), trackRadius*sin(x+0.005));
glVertex3f((trackRadius+1)*cos((double)x+0.005), trackHeight*sin(trackNumberOfHills*(x+0.005)), (trackRadius+1)*sin(x+0.005));
glPopMatrix();
glEnd();
The above code is used to display lines between two railroad tracks which are generated and displayed just fine when the above code is removed. A kart is also displayed fine.
I've discovered that if I remove glPushMatrix(); and glPopMatrix(); everything displays fine, but I need the matrix push/pop lines don't I?
Edit 1:
This is the full code I call to display my track in a class Track.cpp called from my main glut .cpp
void Track::RenderTrack()
{
double x=-3.14;
glNewList(1, GL_COMPILE); // create sphere display list for Object 1
glutSolidSphere(0.1,20,20);
glEndList();
glNewList(2, GL_COMPILE);
for (x; x<3.14;x= x+.005)
{
//first track
glPushMatrix();
glColor3f(1.0,0.0,0.0);
glTranslatef(trackRadius*cos((double)x),trackHeight * sin((double)trackNumberOfHills*x),trackRadius*sin((double)x));
glCallList(1);
glPopMatrix();
//Second track
glPushMatrix();
glColor3f(0.0,1.0,0.0);
glTranslatef((trackRadius+1)*cos(x),trackHeight * sin(trackNumberOfHills*x),(trackRadius+1)*sin(x));
glCallList(1);
glPopMatrix();
//Track Insides
glBegin(GL_QUADS);
glPushMatrix();
glVertex3f(trackRadius*cos((double)x), trackHeight*sin(trackNumberOfHills*x), trackRadius*sin(x));
glVertex3f((trackRadius+1)*cos((double)x), trackHeight*sin(trackNumberOfHills*x), (trackRadius+1)*sin(x));
glVertex3f(trackRadius*cos((double)x+(0.005)), trackHeight*sin(trackNumberOfHills*(x+0.005)), trackRadius*sin(x+0.005));
glVertex3f((trackRadius+1)*cos((double)x+0.005), trackHeight*sin(trackNumberOfHills*(x+0.005)), (trackRadius+1)*sin(x+0.005));
glPopMatrix();
glEnd();
}
glEndList();
glCallList(2); // call the list to draw it
}
From opengl documentation:
Only a subset of GL commands can be used between glBegin and glEnd. The commands are glVertex, glColor, glSecondaryColor, glIndex, glNormal, glFogCoord, glTexCoord, glMultiTexCoord, glVertexAttrib, glEvalCoord, glEvalPoint, glArrayElement, glMaterial, and glEdgeFlag. Also, it is acceptable to use glCallList or glCallLists to execute display lists that include only the preceding commands. If any other GL command is executed between glBegin and glEnd, the error flag is set and the command is ignored.
glPushMatrix and glPopMatrix are not in this list, so your code is ignored.
You can put them outside the glBegin / glEnd block.
I have a tile engine using orthographic projection in immediate mode and I'm just trying to draw a 3d cube on top of my tile scene, in hopes that I can eventually incorporate 3d models into my engine instead of just sprites / textured quads. I would also like to make the tiles 3d for that slight bit of extra eye candy.. Hopefully I can eventually convert this to use modern OpenGL so I can take advantage of those extra features. Not on the top of my priority list at the moment. So on to the question.
I'm initializing OpenGL with this:
void initGL()
{
glDisable(GL_DEPTH_TEST);
glViewport( 0,0,SCREEN_WIDTH,SCREEN_HEIGHT);
//Initialize Projection Matrix
glMatrixMode( GL_PROJECTION );
glPushMatrix();
glLoadIdentity();
//Initialize Modelview Matrix
glMatrixMode( GL_MODELVIEW );
glPushMatrix();
glLoadIdentity();
glOrtho(0,SCREEN_WIDTH,SCREEN_HEIGHT,0,0,1);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
//...setting some various other attributes, omitted for brevity...
glEnable(GL_TEXTURE_2D);
glClearColor( 0, 0, 0, 0 );
}
I have a function for drawing a cube that works.
void draw_cube()
{
/* position object */
glRotatef(30.0F, 1.0F, 0.0F, 0.0F);
glRotatef(30.0F, 0.0F, 1.0F, 0.0F);
/* draw six faces of a cube */
glBegin(GL_QUADS);
...vertices... (removed for brevity)
glEnd();
}
I made 2 functions for setting the 2d and 3d projection modes.
void set3d()
{
glEnable(GL_DEPTH_TEST);
glClear(GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(0,SCREEN_WIDTH,0,SCREEN_HEIGHT, 0,1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void set2d()
{
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,SCREEN_WIDTH,SCREEN_HEIGHT,0,0,1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
For the sake of completeness, some pseudocode of my textured quad drawing..
pushmatrix();
translate();
rotate();
-translate();
glbegin();
...vertices
glend();
popmatrix();
So far I have managed to get the cube to draw on top of the tiles, but it disappears after approximately 1 second to never be seen again until I run the program again.
Basically what I'm doing in the main loop is this:
move objects around, process collisions, etc.
set2d();
draw textured quads, lines, text, etc. in 2d mode.
set3d();
draw_cube();
My question is: Why is the cube disappearing, and are there any errors in my set2d() and set3d() functions?
You have quite a few problems in this code, too many to list in comments in fact.
Your projection matrices are changing the handedness of your post-projected coordinate space, which will affect polygon winding.
Stick to a single handedness, unless you want to reverse the direction used for front- / back-facing polygon facets (glFrontFace (...)) - it is CCW by default, but you will have to change it to CW when you use set3d (...) to maintain consistent behavior.
This problem arises because you have the Y-axis going different directions
The behavior your are describing, where the object appears briefly and then disappears is indicative of an issue with your matrix stack.
Are you calling initGL (...) more than once in your software? You will run into a stack overflow if you do this enough times since you needlessly push the current matrix onto the stack and never pop it off.
You cannot use 0.0 for zNear with a perspective projection matrix, this will result in wonky math during the perspective divide step that comes after transformation to clip-space; the depth buffer will not work correctly.
In fact, glFrustum (...) will generate a GL_INVALID_VALUE error and do exactly nothing if you pass a value ≤ 0.0 for zNear. On a related note, gluPerspective (...) will not do this since it is not actually part of OpenGL, but it is equally invalid behavior to pass such a value to gluPerspective (...).
I'm new to OpenGL, and I've been going through NeHe's tutorials and various other web sources, and I'm testing some things to render text as a HUD of sorts over everything else.
After a very long night, I can't get this to work and I can't find any solutions here that work, so I thought I'd ask.
My code:
GLvoid glLoadHUD(GLvoid)
{
glPushAttrib(GL_LIGHTING_BIT |
GL_DEPTH_BUFFER_BIT |
GL_TEXTURE_BIT);
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
glDisable(GL_TEXTURE_2D);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f);
glRasterPos2f(0.1f, 0.6f);
glColor3f(1.0f,1.0f,1.0f);
glPrint("Test.");
glRasterPos2f(0.0f, 0.0f);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopAttrib();
glEnable(GL_TEXTURE_2D);
glEnable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST);
}
Which is the code to render the text, and this is the code for drawing the scene:
int DrawGLScene(GLvoid)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clears buffers
glLoadIdentity();
// If I put glLoadHUD(); here, it renders but the models render over it,
// which is useless.
for (xloop = 0; xloop < 3;)
{
glLoadIdentity();
glTranslatef(-4.0f+(float(xloop)*4.0f),0.0f,-12.0f);
glCallList(dlstBox); // This is the call to create a box.
xloop++;
}
glLoadHUD(); // If I put it here though, it doesn't render at all.
return TRUE;
}
Thank you in advance for any help you could give, I know I'm pretty green and I'm sure it's staring me right in the face, but this is driving me mad and I'm not sure how to make it work.
With glLoadHud after the rest of the scene, your MODELVIEW matrix is still on the stack, and you do not clear it as part of glLoadHud. Thus all of the glTranslatef translations that you accumulate during the scene are still active when you're drawing the hud, which translates it right out of your viewable window.
Clear the MODELVIEW matrix as part of the start of glLoadHud and see if that makes a difference.
It might be printing inside your z-clipping so it will not show up on your screen. So, move out of the screen a little bit and see if it shows up.
Using the glrotatef() function rotates the figure by a specified angle with respect to the origin. How do I rotate the same figure with respect to another point without making use of transformation matrices manually? Thanks!
void display(){
glClear(GL_COLOR_BUFFER_BIT);
gluOrtho2D(0,499,0,499);
glMatrixMode(GL_PROJECTION);
glColor3f(1,0,0);
drawhouse();
glFlush();
glColor3f(0,0,1);
glTranslatef(0.5 ,0.5,0.5);
glRotatef(45,1,1,1);
glTranslatef(-0.5 ,-0.5,-0.5);
drawhouse();
glFlush();
}
Here's a screenshot for what happens. http://postimage.org/image/q81bhupw/
Basically:
If you want to rotate around P, translate by -P (so that P moves to the origin), then perform your rotation, then translate by P (so that the origin moves back to P).
glTranslatef(P.x, P.y, P.z);
glRotatef(angle, A.x, A.y, A.z);
glTranslatef(-P.x, -P.y, -P.z);
(Note: This is in "reverse order" because the last transformation added is the first one applied, under OpenGL rules.)
So in your setup code, you need these calls:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, 499, 0, 499);
glMatrixMode(GL_MODELVIEW);
And then your display() method should look something like this:
void display() {
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.5f, 0.5f, 0.5f);
glRotatef(45.f, 1.f, 1.f, 1.f);
glTranslatef(-0.5f, -0.5f, -0.5f);
glColor3f(0.f, 0.f, 1.f);
drawhouse();
glFlush();
}
Your code has quite a few problems. First, you have to apply the transformation on the moelview matrix and not the projection matrix. Second, you should wrap you transformation into a glPushMatrix/glPopMatrix, otherwise, they aren't reversed when rendering the next frame. Third, you should apply gluOrtho2d on the projection matrix and not the modelview matrx.
In accordance to John's answer your code should look like:
void display(){
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0,499,0,499);
glMatrixMode(GL_MODELVIEW);
glColor3f(1,0,0);
drawhouse();
glFlush();
glColor3f(0,0,1);
glPushMatrix();
glTranslatef(0.5 ,0.5,0.5);
glRotatef(45,1,1,1);
glTranslatef(-0.5 ,-0.5,-0.5);
drawhouse();
glPopMatrix();
glFlush();
}
EDIT: Even (or because) you are afraid of matrices, I suggest you to read some introductory material on vector and matrix operations and transformations. And you should also read some introductory material on OpenGL, to really understand how it works, especially the state machine principle.