I would like to create a snowman in OpenGL 2.0. I would like to rotate the entire shape, but every time I run the program it doesn't work.
glPushMatrix();
//bottom sphere
glTranslated(tranX,tranY-2,tranZ);
glRotated(rotX,1,0,0);
glRotated(rotY,0,1,0);
glRotated(rotZ,0,0,1);
glScaled(scaX,scaY,scaZ);
glColor3f(1.1,.7,.99);
glutSolidSphere(1.5,30,30);
//middle sphere
glTranslated(tranX,tranY+2.3,tranZ+8);
glRotated(rotX,1,0,0);
glRotated(rotY,0,1,0);
glRotated(rotZ,0,0,1);
glScaled(scaX,scaY,scaZ);
glColor3f(1.1,.7,.99);
glutSolidSphere(1.3,30,30);
//top sphere
glTranslated(tranX,tranY+2,tranZ+10);
glRotated(rotX,1,0,0);
glRotated(rotY,0,1,0);
glRotated(rotZ,0,0,1);
glScaled(scaX,scaY,scaZ);
glColor3f(1.1,.7,.99);
glutSolidSphere(1,30,30);
glPopMatrix();
The thing to know about OpenGL transformations is that they modify the current coordinate system, and not individual objects. For example, when you call glRotated, it rotates the coordinate system the provided angle around the axis supplied, and affects every bit of geometry you render after calling it, until you change or replace the matrix (by calling glPopMatrix, glLoadMatrix, etc.).
In your example, you rotate each sphere of the snowman, but don't have an overarching rotation that affects all of the objects in the scene. Try placing the rotation(s) that you want to affect the entire scene immediately after the glPushMatrix call at the top of your routine.
Related
I've read through several over-complicated articles on rendering a 3D scene with OpenGL, and haven't really found something that helps me to visualize the basic concepts of scene navigation with respect to glRotate and glTranslate calls.
From experimenting with the examples provided by LWJGL (my particular OpenGL library), I understand very basically what effect comes of their use. I can use glTranslate to move to a point, glRotate to rotate about that point, and glLoadIdentity to snap back to the origin or glPopMatrix to go back to the last glPushMatrix, which are essentially snapshots of a location and rotation. Finally, the scene will render to screen with respect to the origin.
So basically, to put a cube at point A with rotation B:
glTranslate(A.x,A.y,A.z) [now focused on point A]
glRotate(B.,,*,*) for pitch, yaw, and roll; [now rotated to rotation B]
glBegin(GL_QUADS) and glVertex3f()x4 for each 'side'(quad) relative to object's origin
glEnd()
glLoadIdentity() [reset to origin for other objects, not needed if only drawing the cube]
As for the "camera", since openGL's "eye" is fixed, the scene has to move inversely from the camera in order to simulate moving the eye with the camera. This is my understanding so far, and if this is wrong, please put me on the right path.
Now for my specific situation and question:
My 'scene' consists of terrain and a player (some arbitrary shape, located at a terrain-relevant location and a 'camera' head). The view should rotate with respect to the player, and the player move with respect to the terrain. I want the final rendering to essentially "look through" the player's head, or camera. My confusion is with the order of translate/rotate calls for rendering each part, and the direction of translation. Is the following the proper way to render the terrain and player with respect to the player's "camera"?
translate away from the player by the player's distance from origin (move the scene)
rotate away from the player's rotation (player looks 40 degrees right, so rotate scene 40 left)
render terrain
reset via glLoadIdentity
render player's head (if needed)
translate to body/hands/whatever position
rotate away from the player's rotation (step 2 again)
render body/hands/whatever
Also, does rotating have an effect on translation? Aka, does OpenGL translate with respect to the rotation, or does rotation have no bearing on translation?
I can use glTranslate to move to a point, glRotate to rotate about that point, and glLoadIdentity to snap back to the origin or glPopMatrix to go back to the last glPushMatrix, which are essentially snapshots of a location and rotation.
No not quite. Those functions have now idea of what a scene is. All they do is manipulating matrices. Here's an excellent article about it:
http://www.opengl.org/wiki/Viewing_and_Transformations
One important thing to keep in mind when working with OpenGL is, that it is not a scene graph. All it does is rendering flat points, lines and triangles to the framebuffer. There's no such thing like a scene you navigate.
So basically, to put a cube at point A with rotation B:
(...)
Yes, you got that one right.
As for the "camera", since openGL's "eye" is fixed
Well, OpenGL got no camera. It's only pushing vertices through the modelview matrix, does lighting calculations on them, then passes them through the projection and maps them to the viewport.
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 implementing a simple camera system in OpenGL. I set up gluPerspective under the projection matrix and then use gluLookAt on the ModelView matrix. After this I have my main render loop which checks for keyboard events and, if any of the arrow keys are pressed, modifies angular and forward speeds (I only rotate through the y axis and move through the z (forwards)). Then I move the view using the following code (deltaTime is the amount of time since the last frame was rendered in seconds, in order to decouple movement from framerate):
//place our camera
newTime = RunTime(); //get the time since app start
deltaTime = newTime - time; //get the time since the last frame was rendered
time = newTime;
glRotatef(view.angularSpeed*deltaTime,0,1,0); //rotate
glTranslatef(0,0,view.forwardSpeed*deltaTime); //move forwards
//draw our vertices
draw();
//swap buffers
Swap_Buffers();
Then the code loops around again. My draw algorithm begins with a glPushMatrix() and ends in a glPopMatrix().
Each call to glRotatef() and glTranslatef() pushes the view forwards by the forwards speed in the direction of view.
However when I run the code, my object is drawn in the correct place, but when I move the movement is done with the orientation of the world origin (0,0,0 - facing along the Z axis) as opposed to the local orientation (where I'm pointing) and when I rotate, the rotation is done about (0,0,0) and not the position of the camera.
I end up with this strange effect of my camera orbiting (0,0,0) as opposed to rotating on the spot.
I do not call glLoadIdentity() at all anywhere inside the loop, and I am sure that the Matrix Mode is set to GL_MODELVIEW for the entire loop.
Another odd effect is if I put a glLoadIdentity() call inside the draw() function (between the PushMatrix and PopMatrix calls, the screen just goes black and no matter where I look I can't find the object I draw.
Does anybody know what I've messed up in order to make this orbit (0,0,0) instead of rotate on the spot?
glRotate() rotates the ModelView Matrix around the World Origin, so to rotate around some arbitrary point, you need to translate your matrix to have that point at the origin, rotate and then translate back to where you started.
I think what you need is this
float x, y, z;//point you want to rotate around
glTranslatef(0,0,view.forwardSpeed*deltaTime); //move forwards
glTranslatef(x,y,z); //translate to origin
glRotatef(view.angularSpeed*deltaTime,0,1,0); //rotate
glTranslatef(-x,-y,-z); //translate back
//draw our vertices
draw();
//swap buffers
Swap_Buffers();
Swap your rotate and translate calls around :)
Since they post-multiply the matrix stack the last the be called is the 'first' to be applied conceptually, if you care about that sort of thing.
I think you first have to translate your camera to point (0,0,0) then rotate, then translate it back.
I've been working on a game engine for awhile. I've started out with 2D Graphics with just SDL but I've slowly been moving towards 3D capabilities by using OpenGL. Most of the documentation I've seen about "how to get things done," use GLUT, which I am not using.
The question is how do I create a "camera" in OpenGL that I could move around a 3D environment and properly display 3D models as well as sprites (for example, a sprite that has a fixed position and rotation). What functions should I be concerned with in order to setup a camera in OpenGL camera and in what order should they be called in?
Here is some background information leading up to why I want an actual camera.
To draw a simple sprite, I create a GL texture from an SDL surface and I draw it onto the screen at the coordinates of (SpriteX-CameraX) and (SpriteY-CameraY). This works fine but when moving towards actual 3D models it doesn't work quite right. The cameras location is a custom vector class (i.e. not using the standard libraries for it) with X, Y, Z integer components.
I have a 3D cube made up of triangles and by itself, I can draw it and rotate it and I can actually move the cube around (although in an awkward way) by passing in the camera location when I draw the model and using that components of the location vector to calculate the models position. Problems become evident with this approach when I go to rotate the model though. The origin of the model isn't the model itself but seems to be the origin of the screen. Some googling tells me I need to save the location of the model, rotate it about the origin, then restore the model to its origal location.
Instead of passing in the location of my camera and calculating where things should be being drawn in the Viewport by calculating new vertices, I figured I would create an OpenGL "camera" to do this for me so all I would need to do is pass in the coordinates of my Camera object into the OpenGL camera and it would translate the view automatically. This tasks seems to be extremely easy if you use GLUT but I'm not sure how to set up a camera using just OpenGL.
EDIT #1 (after some comments):
Following some suggestion, here is the update method that gets called throughout my program. Its been updated to create perspective and view matrices. All drawing happens before this is called. And a similar set of methods is executed when OpenGL executes (minus the buffer swap). The x,y,z coordinates are straight an instance of Camera and its location vector. If the camera was at (256, 32, 0) then 256, 32 and 0 would be passed into the Update method. Currently, z is set to 0 as there is no way to change that value at the moment. The 3D model being drawn is a set of vertices/triangles + normals at location X=320, Y=240, Z=-128. When the program is run, this is what is drawn in FILL mode and then in LINE mode and another one in FILL after movement, when I move the camera a little bit to the right. It likes like may Normals may be the cause, but I think it has moreso to do with me missing something extremely important or not completely understanding what the NEAR and FAR parameters for glFrustum actually do.
Before I implemented these changes, I was using glOrtho and the cube rendered correctly. Now if I switch back to glOrtho, one face renders (Green) and the rotation is quite weird - probably due to the translation. The cube has 6 different colors, one for each side. Red, Blue, Green, Cyan, White and Purple.
int VideoWindow::Update(double x, double y, double z)
{
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glFrustum(0.0f, GetWidth(), GetHeight(), 0.0f, 32.0f, 192.0f);
glMatrixMode( GL_MODELVIEW );
SDL_GL_SwapBuffers();
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glRotatef(0, 1.0f, 0.0f, 0.0f);
glRotatef(0, 0.0f, 1.0f, 0.0f);
glRotatef(0, 0.0f, 0.0f, 1.0f);
glTranslated(-x, -y, 0);
return 0;
}
EDIT FINAL:
The problem turned out to be an issue with the Near and Far arguments of glFrustum and the Z value of glTranslated. While change the values has fixed it, I'll probably have to learn more about the relationship between the two functions.
You need a view matrix, and a projection matrix. You can do it one of two ways:
Load the matrix yourself, using glMatrixMode() and glLoadMatrixf(), after you use your own library to calculate the matrices.
Use combinations of glMatrixMode(GL_MODELVIEW) and glTranslate() / glRotate() to create your view matrix, and glMatrixMode(GL_PROJECTION) with glFrustum() to create your projection matrix. Remember - your view matrix is the negative translation of your camera's position (As it's where you should move the world to relative to the camera origin), as well as any rotations applied (pitch/yaw).
Hope this helps, if I had more time I'd write you a proper example!
You have to do it using the matrix stack as for object hierarchy,
but the camera is inside the hierarchy so you have to put the inverse transform on the stack before drawing the objects as openGL only uses the matrix from 3D to camera.
If you have not checked then may be looking at following project would explain in detail what "tsalter" wrote in his post.
Camera from OGL SDK (CodeColony)
Also look at Red book for explanation on viewing and how does model-view and projection matrix will help you create camera. It starts with good comparison between actual camera and what corresponds to OpenGL API. Chapter 3 - Viewing
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