I know OpenGL itself is a frequently asked question, but I couldn't find a solution to this specific problem I'm having. I've been following NeHe's tutorials, and I've ran into some issues which I don't think should be happening:
When calling glRotatef, where the first parameter being the angle, it appears to be the speed of rotation instead.
Example:
glRotatef(0, 0.0f, 1.0f, 0.0f); // despite the constant numbers, the object rotates infinitely
I am using an NSTimer to loop through the drawing method, which I may think be part of the issue.
Instead of the object rotating 360 degrees around like it should, the object's angle will increment to 180 then decrement back to 0. This is the same with 2D and 3D objects.
I saw example code from Apple and other places that didn't have the same problem as I did, but I was never able to figure out what exactly I am doing wrong that gives me these issues.
The code you have there glRotatef(0,0.0f,1.0f,0.0f); does not change the rotation at all, it simply requests a rotation of 0 degrees around the Y axis. If you want an object to rotate smoothly as time progresses I would suggest the following:
Keep a counter that increments every time your timer triggers, then, before you draw whatever object you are displaying, reset the transformation matrix with glLoadIdentity() and then call glRotatef( counter , 0.0f, 1.0f , 0.0f )
Related
So at the moment am working on a game for my coursework which is based around the idea of flying a rocket, I spent too much time thinking about the physics behind it that I completely ignored getting it to move properly.
For example when I were to draw a cone with the top pointing to the sky, and I rotate it on the X axis it rotates properly however if I translate it on the Y axis it moves on the global Y axis instead on it's local coordinate system which would have the Y axis pointing out of the cone's top.
My question is does openGL have a local coordinate system or would I have to somehow make my own transformation matrices, and if so how would I go about doing that.
The way I am doing the transformation and rotation is as follows:
glPushMatrix();
glTranslatef(llmX, llmY + acceleration, llmZ);
glRotatef(rotX, 1.0f, 0.0f, 0.0f);
glRotatef(rotY, 0.0f, 0.0f, 1.0f);
drawRocket();
glPopMatrix();
Here is a picture better explaining what I mean hopefully offers a better explanation.
EDIT: I find it really weird that the rotations seem to work one after the other as in if I rotate it on the X axis once and then proceed to rotate it on the Z axis it rotates from the already rotated X axis instead of the world X axis.
Hoping somebody could help me with understanding this, really need to get it working for my project.
Thank you.
If you are using a translation matrix for moving up (i.e. moving in positive Y direction), no matter where you are in on the matrix stack or in the transformation process, you are going to move the vertices in the positive Y direction.
If you instead want it move in the rotated direction, I suggest translating along the Y axis first, and then rotate to your desired angle. Essentially, push the matrices in the opposite fashion.
I would like to get angle between object and another object. This must be vertical and horizontal angle.
I Have the coordinates of:
posX, posY, posZ
objectX, objectY, objectZ
I tried:
glRotatef( atan2(objectY - posY,objectX - posX)* 180.0f / 3.14f, 0.0f, 0.0f, 1.0f );
glRotatef( atan2(objectZ - posZ,objectX - posX)* 180.0f / 3.14f, 0.0f, 1.0f, 0.0f );
but sometime don't working correctly
Strictly speaking, if you just have two "objects," there's no angle between them. You need a frame of reference.
For example, two points in 2-D don't have an angle between them. If you treat one as the origin, however, you're probably going to want to measure the angle between the second point and the x-axis.
Similarly, in 3-D, you need to have a frame of reference. You won't actually get 1 angle, but 2. One angle goes around the z-axis by 2PI, and the second goes up and down (angle from the xy-plane) PI. Check out Spherical Coordinates to get a good explanation.
With this in mind, you want to:
Translate your first object to the origin.
Translate your second object by the same amount.
Convert the second object's position from cartesian coordinates to spherical coordinates. That link will help.
But wait! What if you care about the orientation of that first object? EG, it's a character looking some direction. You probably want that angle to be dependent on which way he's looking. If he's looking right at it, you probably want 0 radians (0 degrees), and if it's behind him, you probably want PI radians (180 degrees).
The process is the same as above, but you first must transform that second object from world space into "character" space - that coordinate system relevant to that first object. It's mathematically the same as transforming something into camera space. From there just convert the new position of your object from cartesian to spherical coordinates to get your angles.
Suggestions
Don't hardcore π into your code. Use a #define, preferably from a standard or very widely used library.
Don't use the Fixed Function Pipeline. It has been deprecated for I think ~8 years now. It is slow and not customizable.
If you're having a tough time with rotation, it's probably because you're letting OpenGL do it for you. Manage your own rotation matrix. Then you know exactly what you're doing.
You shouldn't need glRotatef to find the angle anyway. OpenGL is just for drawing. Given two objects, you should be able to figure out the angle between them without making any calls to OpenGL. In fact, you shouldn't call OpenGL.
I'm pretty new to openGL, but I have been struggling with why this won't work (not trying to solve a problem necessarily, but just looking to understand the fundamentals)
So basically this draws a grid of triangles that are rotating. What I'm trying to understand is if/how the Push and Pop operations can be removed. When I take them out there is a random scattering. I've tried reversing the rotation after the drawing is complete, switching the translate and rotate commands. I guess the way I see is that I should be able to avoid the push/pop and instead use the rotate each time to increment a few degrees further than the last time, but I'm obviously missing something.
The push/pop matrices are saving/restoring the previous matrix. You can't really avoid doing this, because you would be accumulating translations and rotations.
Remember: glTranslate does not position things. It builds a translation matrix and applies it to the current matrix, whatever that is. So if you do a translate, then rotate, then translate, the last translate will be in the rotated space, not the same space as the rotate.
OpenGL keeps an internal stack of transformation matrices. When you call glPushMatrix() it pushes all the matrices down by one, duplicating the one on the top of the list. This lets you then apply transformations, rotations, scaling etc to your hearts content, and provided you call a glPopMatrix() to remove your newly adjusted transform matrix when you're done, the rest of the 3D world won't change at all.
Note that when I say the rest of the 3D world, that includes your objects the next time your main loop loops. If you don't call glPushMatrix() and then glPopMatrix() you are permanently transforming the world and it will have an (unpredictable) effect on your objects.
So to wrap up, always call glPushMatrix() and glPopMatrix() at the beginning and end of your transformations, unless you know what you're doing and want to have an effect on the rest of the 3D world.
You need to reverse both the translate and rotate commands (in reverse order):
glTranslatef(xF, yF, 0);
glRotatef(angle, 0.0f, 0.0f, 1.0f);
// draw
glRotatef(-angle, 0.0f, 0.0f, 1.0f);
glTranslatef(-xF, -yF, 0);
As #Nicol points out below, it will probably be faster to use glPushMatrix/glPopMatrix, since glRotatef requires building up a rotation matrix with sines and cosines.
What's more, a rotation followed by its inverse rotation may not be exactly the identity due to floating point rounding errors. This means that if you rely on this technique in an inner loop (as you do above), you may accumulate some substantial floating point errors over the course of your entire draw call.
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