-
Moving a 3d object
Here is the code for moving an object through 3D space in my program. Whats wrong with it is that it moves, but not in the right direction. Could anybody tell me what part of this is wrong? Thanks!
Code:
void MATH::UpdatePos(VEC *vPos, float speed)
{
vPos->view.x = vPos->pos.x + sin(vPos->yaw) * sin(vPos->pitch+90);
vPos->view.y = vPos->pos.y + cos(vPos->yaw);
vPos->view.z = vPos->pos.z + cos(vPos->yaw) * -sin(vPos->pitch+90);
// Get the current view vector (the direction we are looking)
CVector3 vVector = vPos->view - vPos->pos;
vVector = Normalize(vVector);
vPos->pos.x += vVector.x * speed; // Add our acceleration to our position's X
vPos->pos.y += vVector.y * speed; // Add our acceleration to our position's Y
vPos->pos.z += vVector.z * speed; // Add our acceleration to our position's Z
vPos->view.x += vVector.x * speed; // Add our acceleration to our view's X
vPos->view.y += vVector.y * speed; // Add our acceleration to our view's Y
vPos->view.z += vVector.z * speed; // Add our acceleration to our view's Z
}
Here are the class defininions if you need them:
Code:
struct CVector3
{
public:
// A default constructor
CVector3() {}
// This is our constructor that allows us to initialize our data upon creating an instance
CVector3(float X, float Y, float Z)
{
x = X; y = Y; z = Z;
}
// Here we overload the + operator so we can add vectors together
CVector3 operator+(CVector3 vVector)
{
// Return the added vectors result.
return CVector3(vVector.x + x, vVector.y + y, vVector.z + z);
}
// Here we overload the - operator so we can subtract vectors
CVector3 operator-(CVector3 vVector)
{
// Return the subtracted vectors result
return CVector3(x - vVector.x, y - vVector.y, z - vVector.z);
}
// Here we overload the * operator so we can multiply by scalars
CVector3 operator*(float num)
{
// Return the scaled vector
return CVector3(x * num, y * num, z * num);
}
// Here we overload the / operator so we can divide by a scalar
CVector3 operator/(float num)
{
// Return the scale vector
return CVector3(x / num, y / num, z / num);
}
float x, y, z;
};
struct VEC
{
CVector3 pos; //The position
float pitch, yaw, roll; //The pitch, yaw, and roll gotten from key input
CVector3 view; //The view vector calculated
};
-
What is the orientation with the yaw and pitch? IE, if you are looking straight with yaw and pitch=0, are you looking down the positive z axis?
You are adding 90 to the argument of sin, probably thinking it's in degrees, but it's in radians, definite bug there.
Few speed optimizations...
Code:
vPos->view.x = vPos->pos.x + sin(vPos->yaw) * sin(vPos->pitch+90);
vPos->view.y = vPos->pos.y + cos(vPos->yaw);
vPos->view.z = vPos->pos.z + cos(vPos->yaw) * -sin(vPos->pitch+90);
// Get the current view vector (the direction we are looking)
CVector3 vVector = vPos->view - vPos->pos;
vVector = Normalize(vVector);
So overkill. First, you are adding vPos->view vector to the directional vector, and then subtracting it away.. waste of time. Second, you are normalizing an already normalized vector. The following code does the same thing.
Code:
CVector3 vVector(sin(vPos->yaw) * sin(vPos->pitch+90), cos(vPos->yaw), cos(vPos->yaw) * -sin(vPos->pitch+90));
Given, the adding 90 to the pitch is still broken, but if that is fixed, and the trig is right (that killed me when making the camera in my own free floating 3d gravity sim, by far hardest part of the whole project), it will work.
You may not even need to keep the view vector at all, as getting the direction it is pointing requires only knowing the yaw and pitch.
Also, consider taking the vectors by pointer/reference rather than by value. Finally, consider doing only one division in the division operator (do a single division to find reciprocal, and then use multiplaction operator), division is typically 5-10x slower than multiplcation, 1 div and 3 muls are usually quite a bit faster than 3 divs.
-
Yes, 0 pitch and yaw is pointing towards the +z axis(into the screen). I will try taking away the +90 thing when I get to my home computer. Thanks for the optomizations, too
-
Make sure you know the way your screen geometry has your cartesian system defined-- right-handed or left-handed.
-
Oh, and by the way-- it's _much_ more effecient to use matrix math for rotations... and surprisingly, it's not as difficult as it seems.
For sake of example, let's assume that your coordinate system has +Y going up, +X going right, and +Z going into the screen.
Please take a moment and draw a cartesian coordinate with three vectors leading off from 0,0,0 for x, y, and z. It will _really_ help because you can actually visualize how easy a matrix is to use this way.
If we turn this coordinate system into a matrix (3x3) and define the coordinates, they look like this:
x = 1,0,0
y = 0,1,0, and
z = 0,0,1
Gee, doesn't that look like an identity matrix! In a 3x3 rotation matrix, because you're working with identities, the vertical columns are equivalent to the axis, and the horizontal rows are equivalent to the coordinates.
As an example, of using this rotation matrix, what happens if we rotate around z (y & z move clockwise) 90 degrees? We use 90 degrees to make it easy to visualize.
Well, that means that the z-coord stays the same (0,0,1), and the z-axis stays the same (0,0,0 to 0,0,1). But look what happens to X and Y:
'x' moved down and left (clockwise), so it's coordinate is now 0,-1,0. And and 'y' moved right and down (clockwise), so it's coordinate is now 1,0,0.
Look what that did to the identity matrix:
x = 0,-1,0
y = 1, 0,0, and
z = 0, 0,1
You have a new identity matrix. Now you simply aply this matrix to each coord you want moved, and voila-- they rotate appropriately.
Very fun stuff :)