Making an object orbit a fixed point in directx? - c++

I am trying to make a very simple object rotate around a fixed point in 3dspace.
Basically my object is created from a single D3DXVECTOR3, which indicates the current position of the object, relative to a single constant point. Lets just say 0,0,0.
I already calculate my angle based on the current in game time of the day.
But how can i apply that angle to the position, so it will rotate?
:(?
Sorry im pretty new to Directx.

So are you trying to plot the sun or the moon?
If so then one assumes your celestial object is something like a sphere that has (0,0,0) as its center point.
Probably the easiest way to rotate it into position is to do something like the following
D3DXMATRIX matRot;
D3DXMATRIX matTrans;
D3DXMatrixRotationX( &matRot, angle );
D3DXMatrixTranslation( &matTrans, 0.0f, 0.0f, orbitRadius );
D3DXMATRIX matFinal = matTrans * matRot;
Then Set that matrix as your world matrix.
What it does is it creates a rotation matrix to rotate the object by "angle" around the XAxis (ie in the Y-Z plane); It then creates a matrix that pushes it out to the appropriate place at the 0 angle (orbitRadius may be better off as the 3rd parameter in the translation call, depending on where your zero point is). The final line multiplies these 2 matrices together. Matrix multiplications are non commutative (ie M1 * M2 != M2 * M1). What the above does is move the object orbitRadius units along the Z-axis and then it rotates that around the point (0, 0, 0). You can think of rotating an object that is held in your hand. If orbitRadius is the distance from your elbow to your hand then any rotation around your elbow (at 0,0,0) is going to form an arc through the air.
I hope that helps, but I would really recommend doing some serious reading up on Linear Algebra. The more you know the easier questions like this will be to solve yourself :)

Related

OpenGl rotations and translations

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

Rotating object along all 3 axes to map to the player's camera LookAt vector

I have a simple 3D LookAt vector, and I wish to rotate the player model (a simple cube) to show where the player/cube is looking at.
For sideways camera movement I've managed to figure it out and do the following:
glTranslatef(position.x, position.y, position.z);
glRotatef(atan2(lookAt.z, lookAt.x) * 180 / PI, 0, 1, 0);
Now I know that to get up-down camera movement to map to the rendered cube model, I need to rotate the cube around it's x and z axes as well, but I can't seem to figure out what formula to use for those two.
OpenGL will rotate the whole coordinate system (whole space, not only a cube) so after first rotation you just need to rotate only around z axis.
// first rotation
glRotatef(-atan2(lookAt.z, lookAt.x) * 180 / PI, 0, 1, 0);
// second rotation
float d = sqrt(pow(lookAt.x,2) + pow(lookAt.z,2));
float pitch = atan2(lookAt.y, d);
glRotatef(pitch * 180 / PI, 0, 0, 1);
First and second rotation:
I assume your model is looking along x axis (red arrow). I also assume lookAt is given relative to the position of the model.
If you're familiar with matrix math, matrices are an easier way to think about it. If you're not familiar with matrices, this series explains how to use them to solve common game development problems: https://www.youtube.com/playlist?list=PLW3Zl3wyJwWNQjMz941uyOIq3Nw6bcDYC Getting good with matrices is a good idea if you want to be a 3D game programmer.
For your problem, you want to make a translation/rotation matrix which will transform the box to the proper place for you. You can make a translation matrix and a rotation matrix individually, and then at the end take the product of the two. I'll try to break that down.
The translation matrix is simple, if your position is then your matrix will be
To construct a rotation matrix, you need to rotate the standard basis vectors the way you want. Then when you create a matrix from those rotated basis vectors, the matrix will rotate other vectors in the same way. As an example of that, take the standard basis vectors:
Now I'm going to rotate and around by 90 degrees clockwise:
Now put them into a matrix:
and you have R is a matrix that rotates things around by 90 degrees.
In your case you want to rotate stuff such that it faces a vector that you provide. That makes things easy, we can calculate our basis vectors from that vector. If your vector is then and we can solve for the other two basis vectors using cross products. You know that the character won't ever roll their view (right?) so we can use the global up vector as well. I'll call the global up vector . In your case you're using y as the "up" dimension so the global up vector will be
Then:
In the first line you do a cross product between the view vector and the up vector to get a vector orthogonal to both - this will serve as the third basis vector after it is normalized, which is the second line. In the third line another cross product generates the second basis vector. These three vectors represent what happens when the standard basis vectors are rotated the way you want them to be. Use them as the columns in a matrix like so:
Now the last step in the math is to make a final matrix that will do both translation and rotation, and this step is easy:
Then load that matrix into OpenGL with glLoadMatrix:
glLoadMatrixf(&M);
All of this gets explained in the video series I linked as well :)

Opengl object looking at another object

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.

Relative rotation of OpenGL Camera

I am currently struggling in finding a formula to rotate my OpenGL "Camera" (I tried do do it via a scene rotation, but have the same issue).
Basically my Camera is at a given position, looking a given point (all indicated to gluLookAt) and I would like to rotate the camera upwards for example, and still looking at the same point.
What should be the right process ?
What input data should I take to decide the amount of movement ? 2D mouse coordinates evolution or 3D unprojected mouse coordinates evolution ?
The trick is to see that a camera-rotation is the same as a scene rotation if you do it at the correct position. Move the camera into the point around which you want to rotate, then rotate the camera, then move back out by the same distance you moved in.
The amount by which you rotate depends on your application. Take G-Earth as an example: if you are close to the surface the rotation is (absolute) small, if you are far from the surface it is large.
If you're creating orbiting(oribitng around LookAt) camera for openGL I sugest you make it with these data:
LookAtPosition- 3D vector
CamUp - 3D unit vector
RelativeCamPosition - 3D unit vector
CamDistance - decimal number
LookAtPosition is a point on which you'll be looking. CamUp is vector that points up from camera, you can see it on this image. It's best to initialize camera at no rotation, so that CamUp = [0,1,0]. Note that it's unit vector so it's magnitude/size/length is always 1. RelativeCamPosition is again unit vector. You get it by taking LookAt to Camera
vector and dividing by it's magnitude, which you'll save in CamDistance. In intialized state it might look as this:
LookAtPosition = [0,0,0]
CamUp = [0,1,0]
RelativeCamPosition = [1,0,0]
CamDistance = 10
You can now get camera position by
CamPosition = LookAtPosition + RelativeCamPosition * CamDistance
But you need to rotate that camera arround right? Well there's a reason for unit vectors - they are easy to use in calculations. I believe you use angles for rotating so you need to use only sine and cosine. Rotate function might look like this:
Rotate(angleX, angleY){
RelativeCamPosition.x = sin(angleX)*cos(angleY);
RelativeCamPosition.z = cos(angleX)*cos(angleY);
RelativeCamPosition.y = sin(angleY);
}
where angleX and angleY are absolute (NOT RELATIVE) rotations in horizontal and vertical direction. You should always use absolute roations because there can be floating point errors while adding. Anyway I just made those calculations on scrap of paper so I hope they're allright.
Edit: I've just noticed that this will work just if your intiial state is like I wrote RelativeCamPosition = [1,0,0]. However it shouldn't be hard to edit them so it works for arbirtary initial state.

How to get maya like rotations?

I am trying to achieve the same rotational effect like Maya in my project.
I have some knowledge on quaternions and the trackball example.
Unfortunately I am still unable to wrap my head around the concept of using the quaternions to get the desired effect.
Basically I am still getting the same issue I had before with the 3d trackball. After flipping the object upside down, and then trying to rotate to the right, the object will rotate to the left. Well actually its my camera rotating around the focus point in the opposite direction.
The problem is that I am using the screen coordinates & trackball to get the old / new vectors and getting the angle of rotation from those two vectors. I will always get the wrong axis of rotation this way.
How should I go about solving this issue?
I don't know Maya so I can only guess that its rotation is like this: if you rotate left-right, it feels natural. Then if you rotate the object up-down 180 degrees, then rotate left-right again, it still feels natural.
If you are familiar with the concept of using a matrix to do transformations (like rotate, scale and translate), well a quaternion is just the same concept but it only allows rotations, so you might want to use it to constrain your transforms to just rotations. In practice, you can use either a matrix or a quaternion to do the same thing.
What you need to do is remember the current quaternion state for the object, then when the next frame of rotation occurs, multiply the new rotation with the old quaternion (in that order) to give you the next frame's quaternion. That will ensure that no matter what orientation the object is in, the next frame's rotation will be applied from the viewer's viewpoint. This is as opposed to some naive rotation where you just say "user is scrolling up/down, therefore alter the object's X-axis rotation", which causes that flipping.
Remember, like matrices, quaternions need to be multiplied in reverse order that the actions are actually applied, which is why I said to multiply the new operation by the existing quaternion.
To finish with an example. Let's say the user is going to perform 2 actions:
On frame 1, the user rotates the object 180 degrees about the X axis (up/down rotation).
On frame 2, the user rotates the object 90 degrees about the Y axis (left/right rotation).
Lets say the object has a quaternion Q. Every frame, you will reset the object to its default coordinates and apply the quaternion Q to rotate it. Now you might initialise it with the identity quaternion, but let's just say the initial quaternion is called Q0.
On frame 1, create a new quaternion R1 which is a "rotate 180 degrees about the X axis" quaternion (you can find some maths to compute such a quaternion). Pre-multiply the new operation by the existing quaternion: Q1 = R1 * Q0.
On frame 2, create a new quaternion R2 which is a "rotate 90 degrees about the Y axis" quaternion. Pre-multiply the new operation by the existing quaternion: Q2 = R2 * Q1.
On frame 1 you will use Q1 to display the object, and on frame 2 you will use Q2. You can simply keep applying any subsequent user actions to the quaternion and it will always be rotated in the viewer's frame of reference.
I think you have problems with changing coordinate system.
Suppose, you want to rotate object in X Axis, then in Y Axis, and then move it and scale. So, you should multiply your transformation maxtrix (at the beginning it equals to itentity matrix) to the rotation matrix (firstly to X, then to Y), then to translation matrix and at the end to scaling matrix. So, when your current matrix multiplies to the resulting matrix, your coordinate systems changes.
To avoid this problem you can use 2 methods:
1) to accumulate your resultig matrix as product of all previous matrices.
2) to use stack, where in the top will be the matrix, which equals to product of all matrices in the bottom of this matrix (in the stack).
P.S. I'm not sure, that it helps you. I never used quaternions in my projects.