I am trying to create some rotation animations in my projects with objects.
Currently to animate the objects, I have written some tween functons which take the params as value from, value to, value time and tweens the object from from Param to to Param and tween the objects movements in the given time. However, I am need to creating some animations which look like the following:
The objects have to be tweened in rotation around a certain side. So, if go by this algorithm, something like:
for(int rotationAmount = 0;rotationAmount<=90;rotationAmount++){
glPushMatrix();
glRotatef(rotationAmount,1,0,0);
Rectangle(500,500,200,100);
glPopMatrix();
}
I still don't get the required effect, since the Rectangle instead of rotating around a certain side looks like rotating around the circumfrence of some big circle and coming back. Would really welcome some suggestions here on how to achieve the above?
glRotatef multiplies current matrix by rotation matrix. Rotation matrix rotates around orign of coordinates. You need to transtate orign to the side of the object, perform rotation, translate back.
point_type point_on_the_side;
for(int rotationAmount = 0;rotationAmount<=90;rotationAmount++){
glPushMatrix();
glTranslatef(-point_on_the_side.x, -point_on_the_side.y, -point_on_the_side.z);
glRotatef(rotationAmount,1,0,0);
glTranslatef(point_on_the_side.x, point_on_the_side.y, point_on_the_side.z);
Rectangle(500,500,200,100);
glPopMatrix();
}
Related
I am building a camera class to look arround a scene. At the moment I have 3 cubes just spread arround to have a good impression of what is going on. I have set my scroll button on a mouse to give me translation along z-axis and when I move my mouse left or right I detect this movement and rotate arround y-axis. This is just to see what happens and play arround a bit. So I succeeded in making the camera rotate by rotating the cubes arround the origin but after I rotate by some angle, lets say 90 degrees, and try to translate along z axis to my surprise I find out that my cubes are now going from left to right and not towards me or away from me. So what is going on here? It seems that z axis is rotated also. I guess the same goes for x axis. So it seems that nothing actually moved in regard to the origin, but the whole coordinate system with all the objects was just rotated. Can anyone help me here, what is going on? How coordinate system works in opengl?
You are most likely confusing local and global rotations. Usual cheap remedy is to change(reverse) order of some of your transformation. However doing this blindly is trial&error and can be frustrating. Its better to understand the math first...
Old API OpeGL uses MVP matrix which is:
MVP = Model * View * Projection
Where Model and View are already multiplied together. What you have is most likely the same. Now the problem is that Model is direct matrix, but View is Inverse.
So if you have some transform matrix representing your camera in oder to use it to transform back you need to use its inverse...
MVP = Model * Inverse(Camera) * Projection
Then you can use the same order of transformations for both Model and Camera and also use their geometric properties like basis vectors etc ... then stuff like camera local movements or camera follow are easy. Beware some tutorials use glTranspose instead of real matrix Inverse. That is correct only if the Matrix contains only unit (or equal sized) orthogonal basis vectors without any offset so no scale,skew,offset or projections just rotation and equal scale along all axises !!!
That means when you rotate Model and View in the same way the result is opposite. So in old code there is usual to have something like this:
// view part of matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotate3f(view_c,0,0,1); // ugly euler angles
glRotate3f(view_b,0,1,0); // ugly euler angles
glRotate3f(view_a,1,0,0); // ugly euler angles
glTranslatef(view_pos); // set camera position
// model part of matrix
for (i=0;i<objs;i++)
{
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glTranslatef(obj_pos[i]); // set camera position
glRotate3f(obj_a[i],1,0,0); // ugly euler angles
glRotate3f(obj_b[i],0,1,0); // ugly euler angles
glRotate3f(obj_c[i],0,0,1); // ugly euler angles
//here render obj[i]
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
note the order of transforms is opposite (I just wrote it here in editor so its not tested and can be opposite to native GL notation ... I do not use Euler angles) ... The order must match your convention... To know more about these (including examples) not using useless Euler angles see:
Understanding 4x4 homogenous transform matrices
Here is 4D version of what your 3D camera class should look like (just shrink the matrices to 4x4 and have just 3 rotations instead of 6):
reper4D
pay attention to difference between local lrot_?? and global grot_?? functions. Also note rotations are defined by plane not axis vector as axis vector is just human abstraction that does not really work except 2D and 3D ... planes work from 2D to ND
PS. its a good idea to have the distortions (scale,skew) separated from model and keep transform matrices representing coordinate systems orthonormal. It will ease up a lot of things latter on once you got to do advanced math on them. Resulting in:
MVP = Model * Model_distortion * Inverse(Camera) * Projection
I have trouble in opengl. I want to rotate my vehicle while moving forward/backward. Here's a picture which shows exactly my problem. Effects of current code are in blue - after moving the car rotates over the starting location and not the current one. I want to have situation in red - in which my vehicle will rotate over current position and later move forward/backward correctly.
My current code:
lxr=sin(angle);
lzr=cos(angle);
xr+=speed*lxr;
zr+=speed*lzr;
totalangle+=angle
glRotatef(totalangle,0.0,1.0,0.0);
glTranslatef(0.0,0.0,xr);
drawVehicle();
You can try to call translate before rotate. glRotatef rotate view matrix and it affects on current view and also matrix glTranslatef.
From the image, I thought you are translating and then rotating, but looking at the code, I see it is not true.
So, it is obvious that you are in the drawVehicle(); function not rendering your object in the center (0,0). You need to render it in the center, rotate and then translate.
Also, your translation is bogus. You are just translating in z direction, not in y :
glTranslatef(0.0,0.0,xr);
You need to do something like this :
glRotatef(totalangle,0.0,1.0,0.0);
glTranslatef(0.0,yOffset,0.0);
drawVehicle(); // render around [0,0]
you have to move the origin of the coordinate system too, in order to rotate your car as you wish.
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.
I have my object's rotation and translation in a quaternion, which I've converted to a matrix[16].
How do I feed that matrix to OpenGL? I'd-a thought I could just glLoadMatrix() with my new, fancy-pants matrix and all would be good, but I'm getting a blank screen.
(I'm a bit of a GL n00b, so type slowly and use small words ;)
My code looks something like this:
glPushMatrix();
[quaternion makeIdentity]; // reset quat
[quaternion setPitch: rotation.x yaw: rotation.y roll: rotation.z]; // Set up with rotation coords (NOTE: setPitch:yaw:roll: is smart about degrees->radians)
GLdouble matrix[16];
[quaternion matrix: &matrix[0]]; // get quat -> matrix
matrix[12] = location.x; // fill in the translation
matrix[13] = location.y;
matrix[14] = location.z;
glLoadMatrixd(matrix);
glScaled(scale.x, scale.y, scale.z);
// draw geometry here -- snip
glPopMatrix();
I think I'm pretty close but, when I use this code, I get a blank display (everything is glClearColor.)
NOTE: when I skip the quaternion part and do something like this:
glPushMatrix();
glTranslatef(location.x, location.y, location.z);
glRotated(rotation.z, 0, 0, 1.0);
glRotated(rotation.x, 1.0, 0, 0);
glRotated(rotation.y, 0, 1.0, 0);
// draw geometry here -- snip
glPopMatrix();
the display is as expected. The only problem is that my rotations are screwy, due to being applied sequentially. Hence my desire to use quaternions.
If you don't forgot to set current matrix mode to GL_MODELVIEW, your matrix should be loaded correctly. Check your quat -> matrix calculations. I'd start from rotation by zero angle and comparing result with identity matrix.
Quaternions don't have a translation part. The translation must be maintained separately, as is the case in the second code snippet.
I'm not sure the code will do what's desired, anyway. Quaternions won't solve gimbal lock, if the problem is being stated in the very way that introduces gimbal lock in the first place. If the quaternion is being set afresh from pitch/yaw/roll each frame, there will be the same problems as before, and for the same reasons. (And if it appears that's not the case, that's because the quaternion construction code is doing the same thing that the matrix construction code could do, but in this case doesn't: rotating about each rotated axis in turn, rather than rotating about a fixed one.)
To fix this, maintain a quaternion as part of the object's state, and apply each rotation to it directly. This doesn't really buy one much that couldn't be done just as easily with a matrix, though. (I haven't counted the operations, so that's not so say that it may turn out to be rather more efficient one way rather than the other.)
The main advantage of quaternions is that it's easy to interpolate between them, getting something reasonable at each intermediate step, simply by summing the weighted inputs and normalizing the result. SLERP is also an option. The equivalent operation on matrices comes unstuck in certain situations (e.g., with two matrices representing opposing orientations, you'll end up with a column consisting entirely of zeros...), and trying to do something similar with pitch/yaw/roll just generates a big mess.
As for turning one into a matrix, if you've got a quaternion whose vector part is (qx,qy,qz) and whose scalar part is qw, you can turn it into an OpenGL matrix using code like this:
mtx[0]=1.f-2.f*qy*qy-2.f*qz*qz;
mtx[1]=0.f+2.f*qx*qy+2.f*qw*qz;
mtx[2]=0.f+2.f*qx*qz-2.f*qw*qy;
mtx[3]=0.f;
mtx[4]=0.f+2.f*qx*qy-2.f*qw*qz;
mtx[5]=1.f-2.f*qx*qx-2.f*qz*qz;
mtx[6]=0.f+2.f*qy*qz+2.f*qw*qx;
mtx[7]=0.f;
mtx[8]=0.f+2.f*qx*qz+2.f*qw*qy;
mtx[9]=0.f+2.f*qy*qz-2.f*qw*qx;
mtx[10]=1.f-2.f*qx*qx-2.f*qy*qy;
mtx[11]=0.f;
mtx[12]=0.f;
mtx[13]=0.f;
mtx[14]=0.f;
mtx[15]=1.f;
The above was search-and-replace-ed into the above form, so I really hope I didn't screw it up.
Using OpenGL I'm attempting to draw a primitive map of my campus.
Can anyone explain to me how panning, zooming and rotating is usually implemented?
For example, with panning and zooming, is that simply me adjusting my viewport? So I plot and draw all my lines that compose my map, and then as the user clicks and drags it adjusts my viewport?
For panning, does it shift the x/y values of my viewport and for zooming does it increase/decrease my viewport by some amount? What about for rotation?
For rotation, do I have to do affine transforms for each polyline that represents my campus map? Won't this be expensive to do on the fly on a decent sized map?
Or, is the viewport left the same and panning/zooming/rotation is done in some otherway?
For example, if you go to this link you'll see him describe panning and zooming exactly how I have above, by modifying the viewport.
Is this not correct?
They're achieved by applying a series of glTranslate, glRotate commands (that represent camera position and orientation) before drawing the scene. (technically, you're rotating the whole scene!)
There are utility functions like gluLookAt which sorta abstract some details about this.
To simplyify things, assume you have two vectors representing your camera: position and direction.
gluLookAt takes the position, destination, and up vector.
If you implement a vector class, destinaion = position + direction should give you a destination point.
Again to make things simple, you can assume the up vector to always be (0,1,0)
Then, before rendering anything in your scene, load the identity matrix and call gluLookAt
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt( source.x, source.y, source.z, destination.x, destination.y, destination.z, 0, 1, 0 );
Then start drawing your objects
You can let the user span by changing the position slightly to the right or to the left. Rotation is a bit more complicated as you have to rotate the direction vector. Assuming that what you're rotating is the camera, not some object in the scene.
One problem is, if you only have a direction vector "forward" how do you move it? where is the right and left?
My approach in this case is to just take the cross product of "direction" and (0,1,0).
Now you can move the camera to the left and to the right using something like:
position = position + right * amount; //amount < 0 moves to the left
You can move forward using the "direction vector", but IMO it's better to restrict movement to a horizontal plane, so get the forward vector the same way we got the right vector:
forward = cross( up, right )
To be honest, this is somewhat of a hackish approach.
The proper approach is to use a more "sophisticated" data structure to represent the "orientation" of the camera, not just the forward direction. However, since you're just starting out, it's good to take things one step at a time.
All of these "actions" can be achieved using model-view matrix transformation functions. You should read about glTranslatef (panning), glScalef (zoom), glRotatef (rotation). You also should need to read some basic tutorial about OpenGL, you might find this link useful.
Generally there are three steps that are applied whenever you reference any point in 3d space within opengl.
Given a Local point
Local -> World Transform
World -> Camera Transform
Camera -> Screen Transform (usually a projection. depends on if you're using perspective or orthogonal)
Each of these transforms is taking your 3d point, and multiplying by a matrix.
When you are rotating the camera, it is generally changing the world -> camera transform by multiplying the transform matrix by your rotation/pan/zoom affine transformation. Since all of your points are re-rendered each frame, the new matrix gets applied to your points, and it gives the appearance of a rotation.