Home > Blockchain >  How to get angles from 3 vectors representing the local axis rotations
How to get angles from 3 vectors representing the local axis rotations

Time:09-09

I have 3 vectors that represent the 3 local axis of an object I want to get the rotation from:

enter image description here

Red - Y local vector

Green - Z local vector

Blue - X local vector

I need to get the rotation quaternion to provide it to the rendering pipeline and the code base in C offers what appears to be a comprehensive quaternions library but unfortunately I don't fully dominate quaternions. I tried to read many different materials regarding quaternions and I more or less understand the concept but I still am not entirely sure on how to use them.

I would like if someone could point me the steps I have to take to obtain the total rotation quaternion. I think I'm creating the quaternion for each axis correctly but then I don't know what to do with them (and if I try to use just a single one it gives cursed results):

quat getAxisQuaternion(vec3 axisVector, vec3 referenceAxisVector)
{
    axisVector = axisVector.normal();
    vec3 a = axisVector.cross(referenceAxisVector);
    float w = sqrt((axisVector.length() * axisVector.length()) * (referenceAxisVector.length() * referenceAxisVector.length()))   axisVector.dot(referenceAxisVector);
    return quat(a.x, a.y, a.z, w);
}

//...

quat xQuaternion=getAxisQuaternion((leftJoint-rightJoint), vec3(1,0,0));
quat yQuaternion=getAxisQuaternion((lowJoint-upperJoint), vec3(0,1,0));
quat zQuaternion=getAxisQuaternion((frontJoint-backJoint), vec3(0,0,1));

EDIT:

I managed to go further with the following changes:

quat getAxisQuaternion(vec3 axisVector, vec3 referenceAxisVector, float angleOffset=0)
{
    axisVector = axisVector.normal();
    vec3 a = axisVector.cross(referenceAxisVector);
    float w = sqrt((axisVector.length() * axisVector.length()) * (referenceAxisVector.length() * referenceAxisVector.length()))   axisVector.dot(referenceAxisVector);
    return quat(a.x, a.y, a.z, w angleOffset).normal();
}

//..

quat xQuaternion=getAxisQuaternion((leftJoint-rightJoint), vec3(1,0,0));
quat yQuaternion=getAxisQuaternion((lowJoint-upperJoint), vec3(0,-1,0), M_PI);
quat zQuaternion=getAxisQuaternion((backJoint-frontJoint), vec3(0,0,1), M_PI);

rot=yQuaternion*zQuaternion;

Essentially I normalized the quaternion, negated the reference y axis (it is inverted in the original tomb raiders engine) and added half rotation offset to make it match to correct rotation placement.

The problem is now the xQuaternion (rot=yQuaternionzQuaternionxQuaternion). Whatever I do I can't seem to make it work as intended.

https://i.imgur.com/HRIeThD.mp4

It rotates in the wrong direction (probably fixable with some signage tweaking) but the main issue is that it rotates twice as much as it should.

If I add an offset of M_PI/2 it only rotates between -45º and 45º (but with the correct rotation speed and polarity):

https://i.imgur.com/xiC7BlB.mp4

It almost feels like my getAxisQuaternion is somehow limiting to just one quadrant.

If I add an offset of M_PI it just wont rotate at all over that axis.

Any ideas?

CodePudding user response:

It seems it really is tricky to do this for more then 2 axis at a time since it basically creates the same limitation of using euler angles to do too many rotations.

I was able to solve the issue using a transformation matrix:

mat4 m;
m.identity();
m.right() = xVector;
m.up() = yVector;
m.dir() = zVector;
rot = m.getRot();

with each vector being changed to a vec4(x, y, z, 0).

Unfortunately I found out my vectors were not properly ortogonal and thus created mayhem near a certain angle. I'm currently trying a different approach but that's out of scope for this topic.

  • Related