we decompose the quaternion as q1 * q2, where q1 is a rotation orthogonal to the unit axis, and q2 a rotation around it. (so for example if 'axis' is the twist axis, this is separateSwingTwist).
| 406 | // we decompose the quaternion as q1 * q2, where q1 is a rotation orthogonal to the unit axis, and q2 a rotation around it. |
| 407 | // (so for example if 'axis' is the twist axis, this is separateSwingTwist). |
| 408 | static PxQuat project(const PxQuat& q, const PxVec3& axis, PxReal cosHalfTol, bool& truncated) |
| 409 | { |
| 410 | const PxReal a = q.getImaginaryPart().dot(axis); |
| 411 | const PxQuat q2 = PxAbs(a) >= 1e-6f ? PxQuat(a*axis.x, a*axis.y, a*axis.z, q.w).getNormalized() : PxQuat(PxIdentity); |
| 412 | const PxQuat q1 = q * q2.getConjugate(); |
| 413 | |
| 414 | PX_ASSERT(PxAbs(q1.getImaginaryPart().dot(q2.getImaginaryPart())) < 1e-6f); |
| 415 | |
| 416 | return truncate(q1, cosHalfTol, truncated) * q2; |
| 417 | } |
| 418 | |
| 419 | // Here's how the angular part works: |
| 420 | // * if no DOFs are locked, there's nothing to do. |
no test coverage detected