I would like to build on top of this question about rotating an object towards specific target with quaternions. My particular use case would be to orient a joint in 3d space towards another or a target point, as the stepping stone for implementing inverse kinematics.
I use glm
math library to calculate dot and cross products. I also use its defined structs, vec3
and quat
.
Here is the relevant code:
quat AxisAngleToQuat(float angle, vec3 axis) {
quat myquat = quat(cos(angle/2), axis.x*sin(angle/2), axis.y*sin(angle/2), axis.z*sin(angle/2));
return myquat;
}
vec3 direction = normalize(targetPos-sourcePos);
float dotProduct = dot(sourceForward, direction);
float angle = acos(dotProduct);
vec3 axis = normalize(cross(sourceForward, direction));
quat myquat;
//Handle special case where dotProduct is 1
if (Math.Abs(dotProduct-1.0f) < 0.000001f) {
myquat = quat(1, 0, 0, 0); //create identity quaternion
}
//Handle special case where dotProduct is -1
else if (Math.Abs(dotProduct+1.0f) < 0.000001f) {
vec3 arbitraryAxis = vec3(0, 1, 0); //we can choose global up as the arbitrary axis
myquat = AxisAngleToQuat((float)M_PI, arbitraryAxis);
}
else {
myquat = AxisAngleToQuat(angle, axis);
}
Now after implementing this and handling all special cases, there's still a problem. When the angle
comes close to 180
degrees (we get close to source object's original backwards direction -sourceForward
), small changes in angle (small translations of target object) result in extreme changes to the source object orientation's.
My question is why does this happen and what can we do dampen this effect?