Archived

This topic is now archived and is closed to further replies.

Rotating the elements of a quaternion

This topic is 4944 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I''m implementing quaternions into a current project of mine and what I dont understand is how I would go about rotating a specific component of the vector portion of the quaternion by the scaler component. Specifically, how would I isolate a rotation along the X, Y, or Z axis in the vector portion of the quaternion using the scalar component of the quaternion?

Share this post


Link to post
Share on other sites
I may be missing something obvious,but I''m not quite sure what you mean. What do you mean by a specific component of the vector portion?

In an axis-angle representation, the vector component of the quaternion is sin(angle/2)axis, and the scalar component is cos(angle/2). Can you perhaps explain more about your question, or about what you''re trying to do?

Share this post


Link to post
Share on other sites
I have the orientation of by object stored as a quaternion. Now lets say that when I press a certain key I want to rotate on either the X, Y, or Z axis. Using the components of the quaternion what equations would I use for the specific axis'' ?

Share this post


Link to post
Share on other sites
Well if it is a local rotation given about an axis you want then:
Construct a quat using the the axis of rotation and rotation angle then:
newquat = rotationquat * objquat

Share this post


Link to post
Share on other sites
"I have the orientation of my object stored as a quaternion. Now lets say that when I press a certain key I want to rotate on either the X, Y, or Z axis. Using the components of the quaternion what equations would I use for the specific axis'' ?"

The first thing you need is a quaternion multiplication function. You should have one as part of your quaternion class, but if you don''t, any reference on quaternions will show you how to implement it. One caveat is that in the book 3D Math Primer they do the quat mult in a different way so that the order of multiplication is more intuitive.

Now, you have your object quaternion. To rotate 5 degrees around the y axis, create a quaternion with angle 5 degrees (probably in radians) and axis 0, 1, 0. Then multiply this by your current quaternion. (I''m not sure about the order of multiplication, but I think the standard order is current = current * yrotation). Now you''ve rotated 5 degrees around the y axis.

If you''re trying to create 6DOF movement like in Descent, you''ll want to rotate around your object''s local axes rather than the world axes.

Does that help?

Share this post


Link to post
Share on other sites
Better yet here you go:
(I cannot vouch for correctness in this code as it is in need of an overhaul, but it was working fine last I used it).

class cTransformation{
public:
cTransformation(){};
cTransformation(cTransformation& cor){
Set(&cor);
}
~cTransformation(){};

void Set(const cTransformation* orient){
orientation.set(&orient->orientation);
position.set(&orient->position);
}

void Set(const QUAT* orient, const VECTOR3D* pos){
orientation.set(orient);
position.set(pos);
}

void SetPosition(const VECTOR3D* _pos){
position.set(_pos);
}

void SetPosition(float x, float y, float z){
position.set(x,y,z);
}


void SetOrientation(float ax, float ay, float az, float angle){
orientation.set(&ROT(ax,ay,az,angle));
}

void SetOrientation(const ROT* rot){
orientation.set(rot);
}

void SetOrientation(const VECTOR3D* euler){
ROT tmpr;
QUAT tmpq;
tmpr.set(0.0f,1.0f,0.0f,euler->x);
orientation.set(&tmpr);
tmpr.set(1.0f,0.0f,0.0f,euler->y);
tmpq.set(&tmpr);
RotateLocal(&tmpq);
tmpr.set(0.0f,0.0f,1.0f,euler->z);
tmpq.set(&tmpr);
RotateLocal(&tmpq);
}

void SetOrientation(const QUAT* quat){
orientation.set(quat);
}

//void RotateGlobal(const ROT& rot);

//void RotateGlobal(const VECTOR3D& euler);

void RotateGlobal(const QUAT* quat){
orientation.mult_set(quat);
}

void RotateGlobal(const cTransformation* cor){
orientation.mult_set(&(cor->orientation));
}

//void RotateLocal(const ROT& rot);

//void RotateLocal(const VECTOR3D& euler);

void RotateLocal(const QUAT* quat){
QUAT tmpq(orientation);
orientation.mult_set(quat,&tmpq);
}

void RotateLocal(const cTransformation* cor){
QUAT tmpq(orientation);
orientation.mult_set(&(cor->orientation),&tmpq);
}

void TranslateGlobal(const VECTOR3D* trans){
position.add_set(trans);
}

void TranslateLocal(const VECTOR3D* trans){
QUAT tmpq(trans);
QUAT tmpq2;

//QUAT vec;

//tmpq.mult_set(orientation.conjugate());

//vec.mult_set(orientation,tmpq);

//position.add_set(vec.v);


tmpq2.mult_set(&tmpq,&orientation);
tmpq.mult_set(&(orientation.conjugate()),&tmpq2);
position.add_set(&tmpq.v);
}

void TranslateLocal(const cTransformation* cor){
QUAT tmpq(&(cor->position));
QUAT tmpq2;
tmpq2.mult_set(&tmpq,&orientation);
tmpq.mult_set(&orientation.conjugate(),&tmpq2);
position.add_set(&tmpq.v);

// QUAT tmpq(cor.position);


// QUAT vec;

// tmpq.mult_set(orientation.conjugate());

// vec.mult_set(orientation,tmpq);

// position.add_set(vec.v);

}


void GetPosition(VECTOR3D* _pos)const{
_pos->set(&position);
}
void GetOrientation(QUAT* _or)const{
_or->set(&orientation);
}

void ConvPosToLocal(const VECTOR3D* targetpos, VECTOR3D* vtt) const{
QUAT tmpq(targetpos);
QUAT vec;

tmpq.v.subtract_set(&position);
//tmpq.mult_set(orientation);

//vec.mult_set(orientation.conjugate(),tmpq);

tmpq.mult_set(&orientation.conjugate());
vec.mult_set(&orientation,&tmpq);

vtt->set(&vec.v);
}

void ConvPosToGlobal(const VECTOR3D* targetpos, VECTOR3D* vtt) const{
QUAT tmpq(targetpos);
QUAT vec;

//tmpq.mult_set(orientation.conjugate());

//vec.mult_set(orientation,tmpq);

tmpq.mult_set(&orientation);
vec.mult_set(&orientation.conjugate(),&tmpq);
vtt->add_set(&vec.v,&position);
}

void ConvOrToLocal(const QUAT* targetor, QUAT* lto) const{
lto->mult_set(&orientation,targetor );
}

void ConvOrToGlobal(const QUAT* targetor, QUAT* gto) const{
gto->mult_set(targetor,&orientation);
}

void ConvTransToLocal(const cTransformation* globaltrans, cTransformation* rt) const{
//rotate local

rt->orientation.mult_set(&orientation,&globaltrans->orientation);
ConvPosToLocal(&globaltrans->position, &(rt->position));
}

void ConvTransToGlobal(const cTransformation* localtrans, cTransformation* rt) const{
//rotate global

rt->orientation.mult_set(&orientation,&localtrans->orientation);
ConvPosToGlobal(&localtrans->position, &(rt->position));
}


float PitchToLocalTarget(const VECTOR3D* localtargetpos)const{
return -(float)atan2(localtargetpos->y,localtargetpos->z);
}

float YawToLocalTarget(const VECTOR3D* localtargetpos)const{
return (float)atan2(localtargetpos->x,localtargetpos->z);
}

float RollToLocalTarget(const VECTOR3D* localtargetpos)const{
return -(float)atan2(localtargetpos->x,localtargetpos->y);
}


void AimAtGlobal(const VECTOR3D* targetpos, DWORD axis_constrain){
VECTOR3D tmpv;
float tmpf;

VECTOR3D rotangles;

if(!(axis_constrain & T_CONSTRAINY)){
ConvPosToLocal(targetpos,&tmpv);
tmpf = (float)atan2(tmpv.x,tmpv.z);
RotateLocal(&QUAT(&ROT(0.0f,1.0f,0.0f,tmpf)));
}

if(!(axis_constrain & T_CONSTRAINX)){
ConvPosToLocal(targetpos,&tmpv);
tmpf = -(float)atan2(tmpv.y,tmpv.z);
RotateLocal(&QUAT(&ROT(1.0f,0.0f,0.0f,tmpf)));
}

if(!(axis_constrain & T_CONSTRAINZ)){
ConvPosToLocal(targetpos,&tmpv);
tmpf = -(float)atan2(tmpv.x,tmpv.y);
RotateLocal(&QUAT(&ROT(0.0f,0.0f,1.0f,tmpf)));
}
}

void AimAtGlobal(const cTransformation* or, DWORD axis_constrain){
AimAtGlobal(&or->position,axis_constrain);
}

void GetMatrix(float *mat) const{
orientation.matrixconv(mat);
mat[12] = position.x;
mat[13] = position.y;
mat[14] = position.z;
}


D3DMATRIX GetMatrix() const{
D3DMATRIX mat;

orientation.matrixconv(&(mat._11));
mat._41 = position.x;
mat._42 = position.y;
mat._43 = position.z;
return mat;
}

void CameraConvertPos(const VECTOR3D *objpos, VECTOR3D* returnpos) const{
QUAT p, vec;

p.v.x = objpos->x - position.x;
p.v.y = objpos->y - position.y;
p.v.z = objpos->z - position.z;
p.w = 0.0f;

p.mult_set(&orientation.conjugate());
vec.mult_set(&orientation,&p);


//p.mult_set(orientation);

//vec.mult_set(orientation.conjugate(), p);

returnpos->set(&vec.v);
};

void CameraConvertOr(const QUAT *objor, QUAT* returnor) const{
//returnor->mult_set(objor->conjugate(),orientation);

returnor->mult_set(objor, &orientation.conjugate());
}

void CameraConvert(const cTransformation* objtrans, cTransformation* rettrans) const{
CameraConvertPos(&(objtrans->position), &(rettrans->position));
CameraConvertOr(&(objtrans->orientation),&(rettrans->orientation));
}


//private:

QUAT orientation;
VECTOR3D position;
};


You will need to modify it though since this code takes into account other class types not mentioned in it, but they are self explanatory.

Share this post


Link to post
Share on other sites
Yea I think I get it, basically all I have to do is set whatever vertex I want to rotate around to '1' and multiply it by the angle you want to rotate by. Taking this approach, would I then convert the quaternion to a 4x4 matrix and perform the rotation?

[edited by - Jon723 on May 30, 2004 10:58:38 PM]

Share this post


Link to post
Share on other sites
No, quaternions can perform rotations themselves.


void mult_set(const QUAT* r, const QUAT* q){
v.x = r->w * q->v.x + r->v.x * q->w + r->v.y * q->v.z - r->v.z * q->v.y;
v.y = r->w * q->v.y + r->v.y * q->w + r->v.z * q->v.x - r->v.x * q->v.z;
v.z = r->w * q->v.z + r->v.z * q->w + r->v.x * q->v.y - r->v.y * q->v.x;
w = r->w * q->w - r->v.x * q->v.x - r->v.y * q->v.y - r->v.z * q->v.z;
};


here v = r * q.
[Edit]: damn funky tabs.

[edited by - SoulSpectre on May 30, 2004 11:04:06 PM]

Share this post


Link to post
Share on other sites
I should have mentioned this earlier....I have the quaternion multiplication operator already implemented. I asked about transforming the quaternion into a matrix because I''m using opengl but could I use glRotatef with the components of the quaternion ?

Share this post


Link to post
Share on other sites
here is to make a matrix:

float wx, wy, wz, xx, yy, yz, xy, xz, zz;// xs, ys, zs;
float x2,y2,z2;

x2 = v.x + v.x; y2 = v.y + v.y; z2 = v.z + v.z;

xx = v.x * x2; xy = v.x * y2; xz = v.x * z2;
yy = v.y * y2; yz = v.y * z2; zz = v.z * z2;
wx = w * x2; wy = w * y2; wz = w * z2;



m[0] = 1.0f - (yy + zz);
m[1] = xy - wz;
m[2] = xz + wy;
m[3] = 0.0f;

m[0+4] = xy + wz;
m[1+4] = 1.0f - (xx + zz);
m[2+4] = yz - wx;
m[3+4] = 0.0f;

m[0+8] = xz - wy;
m[1+8] = yz + wx;
m[2+8] = 1.0f - (xx + yy);
m[3+8] = 0.0f;

m[0+12] = 0.f;
m[1+12] = 0.f;
m[2+12] = 0.f;
m[3+12] = 1.f;


Note: This is for dx so you may have to swizzle the matrix order (ie row major to column major)

Share this post


Link to post
Share on other sites
thanks a lot everyone for all the responses I finally think I have a good grasp of how to get these working in my project....I''ll be back if I have anymore questions.

Share this post


Link to post
Share on other sites