Subscribe to GameDev.net Direct to receive the latest updates and exclusive content.
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.
Posted 22 June 2006 - 12:29 AM
Posted 22 June 2006 - 12:36 AM
Posted 22 June 2006 - 01:43 AM
Posted 22 June 2006 - 03:56 AM
#include <iostream>
#include <cmath>
using namespace std;
void rotate(double &x, double &y, double angle){
double c=cos(angle),s=sin(angle);
double x0 = x;
x = x*c - s*y;
y = x0*s + x0*y;
}
int main(void){
double target_x=1,target_y=2,target_z=3;
double x=1,y=0,z=0;
rotate(y,z,4); // Replace 4 by whatever you want. This is your free parameter
rotate(x,z,atan2(target_z,sqrt(target_x*target_x+target_y*target_y)));
rotate(x,y,atan2(target_y,target_x));
std::cout << x << ',' << y << ',' << z << std::endl;
}
Posted 22 June 2006 - 07:13 AM
double yaw = Math.Atan2(ds.X, ds.Y);
double pitch = Math.Atan2(ds.Z, Math.Sqrt((ds.X * ds.X) + (ds.Y * ds.Y)));
Posted 22 June 2006 - 07:29 AM
Posted 22 June 2006 - 06:21 PM
Quote:
Original post by Code Fusion
k iam goin on a limb here , but if you have the two components of the vectors couldn't you
just calculate the the angle between the two by using Cos^-1(|a|.|b|/|a||b|) ?.
Posted 22 June 2006 - 06:44 PM
Quote:
Original post by Bob Janova
A direction vector can be turned into a pitch and yaw (two Euler angles) thusly:double yaw = Math.Atan2(ds.X, ds.Y);
double pitch = Math.Atan2(ds.Z, Math.Sqrt((ds.X * ds.X) + (ds.Y * ds.Y)));
An axis vector can be rotated into the direction by first rotating along the world Y axis by the pitch, then by the Z by the yaw. But you probably know that already.
I don't think it's possible to have angles about each (world) axis that don't depend on the order of rotations, because changing the order of rotations with the same angles would give you a different direction. I don't know what a Cardan angle is though.
// e- is the conformeE, r- is the conformeR
// - Make both endpoints local to world origin
Vector eVec = bc->GetVector(IPP_ENDPOINT) - bc->GetVector(IPP_ORIGIN);
BaseContainer* bbc = base->GetDataInstance();
Vector rVec = bbc->GetVector(IPP_ENDPOINT) - bbc->GetVector(IPP_ORIGIN);
// - If equivalent, no more processing required
if (VectorEqual(eVec, rVec, EPSILONL)) return;
// - Calculate angular offset between eVec/rVec Vectors in Rotation Order
Real r;
Vector eAngle;
Vector rAngle;
// -- Calculate Euler angles of Conformer
r = Sqrt(rVec.x*rVec.x + rVec.z*rVec.z);
rAngle.y = (r < EPSILONS) ? 0.0f : Support::Angle(rVec.z, rVec.x); // yaw
rAngle.x = -Support::Angle(rVec.y, r); // pitch
rAngle.z = 0.0f; // roll
// -- Concatenate Rotation-order specific matrix
Matrix mat;
LONG ro = bc->GetLong(IPP_RORDER);
if (ro == ROTORDER_XYZ) mat = MatrixMove(Vector(0.0)) * MatrixRotZ(rAngle.z) * MatrixRotY(rAngle.y) * MatrixRotX(rAngle.x) * MatrixScale(Vector(1.0));
else if (ro == ROTORDER_XZY) mat = MatrixMove(Vector(0.0)) * MatrixRotY(rAngle.y) * MatrixRotZ(rAngle.z) * MatrixRotX(rAngle.x) * MatrixScale(Vector(1.0));
else if (ro == ROTORDER_YXZ) mat = MatrixMove(Vector(0.0)) * MatrixRotZ(rAngle.z) * MatrixRotX(rAngle.x) * MatrixRotY(rAngle.y) * MatrixScale(Vector(1.0));
else if (ro == ROTORDER_YZX) mat = MatrixMove(Vector(0.0)) * MatrixRotX(rAngle.x) * MatrixRotZ(rAngle.z) * MatrixRotY(rAngle.y) * MatrixScale(Vector(1.0));
else if (ro == ROTORDER_ZXY) mat = MatrixMove(Vector(0.0)) * MatrixRotY(rAngle.y) * MatrixRotX(rAngle.x) * MatrixRotZ(rAngle.z) * MatrixScale(Vector(1.0));
else if (ro == ROTORDER_ZYX) mat = MatrixMove(Vector(0.0)) * MatrixRotX(rAngle.x) * MatrixRotY(rAngle.y) * MatrixRotZ(rAngle.z) * MatrixScale(Vector(1.0));
// -- Calculate Euler angles of Conformee
// Note that eVec is placed in the coordinate system where rVec is unrotated
eVec *= !mat;
r = Sqrt(eVec.x*eVec.x + eVec.z*eVec.z);
eAngle.y = (r < EPSILONS) ? 0.0f : Support::Angle(eVec.z, eVec.x); // yaw
eAngle.x = -Support::Angle(eVec.y, r); // pitch
eAngle.z = 0.0f; // roll
// These are the rotation angles from Conformee to Conformer Endpoint
Vector rotVec = Vector(-eAngle.x, -eAngle.y, 0.0);
Posted 22 June 2006 - 07:00 PM
Quote:
Original post by jyk
I take it from your post that although you need (non-repeating) Euler angles as the final form, you can use other intermediate representations. If you wish to go through an axis-angle matrix representation, Shoemake's article/code is really the way to go. If you tried this and it didn't work, then there may be more to the problem, either that or we're misunderstanding it somehow. (One potential pitfall is using axis-angle and Euler-extraction functions with non-matching basis vector orientations, so watch out for this. FYI Shoemake's examples use column vectors.)
Posted 23 June 2006 - 01:15 PM
Posted 23 June 2006 - 11:58 PM
// e- is the conformeE, r- is the conformeR
// - Make both endpoints local to world origin
Vector eVec = bc->GetVector(IPP_ENDPOINT) - bc->GetVector(IPP_ORIGIN);
BaseContainer* bbc = base->GetDataInstance();
Vector rVec = bbc->GetVector(IPP_ENDPOINT) - bbc->GetVector(IPP_ORIGIN);
// - If equivalent or either is zero vector (no direction), no more processing required
if (VectorEqual(eVec, rVec, EPSILONL)) return;
if (VectorEqual(eVec, zVec, EPSILONL)) return;
if (VectorEqual(rVec, zVec, EPSILONL)) return;
// - Determine main direction axis for vector
UCHAR axis;
Vector ar = Vector(Abs(rVec.x), Abs(rVec.y), Abs(rVec.z));
// -- X
if ((ar.x > ar.y) && (ar.x > ar.z))
{
Matrix align = MatrixRotX(RAD_90) * MatrixRotZ(RAD_90) * MatrixScale(Vector(1.0));
// new y is old x, new z is old y, new x is old z
rVec *= align;
eVec *= align;
axis = 0;
}
// -- Y
else if (ar.y > ar.z)
{
// new x is old y, new z is old x, new y is old z
Matrix align = MatrixRotY(-RAD_90) * MatrixRotZ(-RAD_90) * MatrixScale(Vector(1.0));
rVec *= align;
eVec *= align;
axis = 1;
}
// -- Z
else axis = 2;
// - Calculate angular offset between eVec/rVec Vectors in Rotation Order
// -- Calculate Euler angles of Conformer
Real r;
Vector eAngle;
Vector rAngle;
r = Sqrt(rVec.x*rVec.x + rVec.z*rVec.z);
rAngle.z = 0.0f; // roll
rAngle.y = (r < EPSILONS) ? 0.0f : Support::Angle(rVec.z, rVec.x); // yaw
rAngle.x = -Support::Angle(rVec.y, r); // pitch
// -- Concatenate Rotation-order specific matrix
Matrix mat = MatrixMove(zVec) * MatrixRotX(rAngle.x) * MatrixRotY(rAngle.y) * MatrixRotZ(rAngle.z) * MatrixScale(Vector(1.0));
// -- Calculate Euler angles of Conformee
// Note that eVec is placed in the coordinate system where rVec is unrotated
eVec *= !mat;
r = Sqrt(eVec.x*eVec.x + eVec.z*eVec.z);
// These are the rotation angles from Conformee to Conformer Endpoint
eAngle.z = 0.0f; // roll
eAngle.y = (r < EPSILONS) ? 0.0f : -Support::Angle(eVec.z, eVec.x); // yaw
eAngle.x = Support::Angle(eVec.y, r); // pitch
// Reorder rotations to avoid roll rotations
Vector rotVec;
if (axis == 0)
{
rotVec.x = eAngle.z;
rotVec.y = eAngle.x;
rotVec.z = eAngle.y;
}
else if (axis == 1)
{
rotVec.x = eAngle.y;
rotVec.y = eAngle.z;
rotVec.z = eAngle.x;
}
else
{
rotVec.x = eAngle.x;
rotVec.y = eAngle.y;
rotVec.z = eAngle.z;
}
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.
GameDev.net™, the GameDev.net logo, and GDNet™ are trademarks of GameDev.net, LLC.