Jolt Physics
A multi core friendly Game Physics Engine
Loading...
Searching...
No Matches
RotationQuatConstraintPart Class Reference

#include <RotationQuatConstraintPart.h>

Public Member Functions

void CalculateConstraintProperties (const Body &inBody1, Mat44Arg inRotation1, const Body &inBody2, Mat44Arg inRotation2, QuatArg inInvInitialOrientation)
 Calculate properties used during the functions below. More...
 
void WarmStart (Body &ioBody1, Body &ioBody2, float inWarmStartImpulseRatio)
 Must be called from the WarmStartVelocityConstraint call to apply the previous frame's impulses. More...
 
bool SolveVelocityConstraint (Body &ioBody1, Body &ioBody2)
 Iteratively update the velocity constraint. Makes sure d/dt C(...) = 0, where C is the constraint equation. More...
 
bool SolvePositionConstraint (Body &ioBody1, Body &ioBody2, QuatArg inInvInitialOrientation, float inBaumgarte) const
 Iteratively update the position constraint. Makes sure C(...) = 0. More...
 
Vec3 GetTotalLambda () const
 Return lagrange multiplier. More...
 
void SaveState (StateRecorder &inStream) const
 Save state of this constraint part. More...
 
void RestoreState (StateRecorder &inStream)
 Restore state of this constraint part. More...
 

Static Public Member Functions

static Quat sGetInvInitialOrientation (const Body &inBody1, const Body &inBody2)
 Return inverse of initial rotation from body 1 to body 2 in body 1 space. More...
 

Detailed Description

Quaternion based constraint that constrains rotation around all axis so that only translation is allowed.

NOTE: This constraint part is more expensive than the RotationEulerConstraintPart and slightly more correct since RotationEulerConstraintPart::SolvePositionConstraint contains an approximation. In practice the difference is small, so the RotationEulerConstraintPart is probably the better choice.

Rotation is fixed between bodies like this:

q2 = q1 r0

Where: q1, q2 = world space quaternions representing rotation of body 1 and 2. r0 = initial rotation between bodies in local space of body 1, this can be calculated by:

q20 = q10 r0 <=> r0 = q10^* q20

Where: q10, q20 = initial world space rotations of body 1 and 2. q10^* = conjugate of quaternion q10 (which is the same as the inverse for a unit quaternion)

We exclusively use the conjugate below:

r0^* = q20^* q10

The error in the rotation is (in local space of body 1):

q2 = q1 error r0 <=> error = q1^* q2 r0^*

The imaginary part of the quaternion represents the rotation axis * sin(angle / 2). The real part of the quaternion does not add any additional information (we know the quaternion in normalized) and we're removing 3 degrees of freedom so we want 3 parameters. Therefore we define the constraint equation like:

C = A q1^* q2 r0^* = 0

Where (if you write a quaternion as [real-part, i-part, j-part, k-part]):

    [0, 1, 0, 0]
A = [0, 0, 1, 0]
    [0, 0, 0, 1]

or in our case since we store a quaternion like [i-part, j-part, k-part, real-part]:

    [1, 0, 0, 0]
A = [0, 1, 0, 0]
    [0, 0, 1, 0]

Time derivative:

d/dt C = A (q1^* d/dt(q2) + d/dt(q1^*) q2) r0^* = A (q1^* (1/2 W2 q2) + (1/2 W1 q1)^* q2) r0^* = 1/2 A (q1^* W2 q2 + q1^* W1^* q2) r0^* = 1/2 A (q1^* W2 q2 - q1^* W1 * q2) r0^* = 1/2 A ML(q1^*) MR(q2 r0^*) (W2 - W1) = 1/2 A ML(q1^*) MR(q2 r0^*) A^T (w2 - w1)

Where: W1 = [0, w1], W2 = [0, w2] (converting angular velocity to imaginary part of quaternion). w1, w2 = angular velocity of body 1 and 2. d/dt(q) = 1/2 W q (time derivative of a quaternion). W^* = -W (conjugate negates angular velocity as quaternion). ML(q): 4x4 matrix so that q * p = ML(q) * p, where q and p are quaternions. MR(p): 4x4 matrix so that q * p = MR(p) * q, where q and p are quaternions. A^T: Transpose of A.

Jacobian:

J = [0, -1/2 A ML(q1^*) MR(q2 r0^*) A^T, 0, 1/2 A ML(q1^*) MR(q2 r0^*) A^T] = [0, -JP, 0, JP]

Suggested reading:

  • 3D Constraint Derivations for Impulse Solvers - Marijn Tamis
  • Game Physics Pearls - Section 9 - Quaternion Based Constraints - Claude Lacoursiere

Member Function Documentation

◆ CalculateConstraintProperties()

void RotationQuatConstraintPart::CalculateConstraintProperties ( const Body inBody1,
Mat44Arg  inRotation1,
const Body inBody2,
Mat44Arg  inRotation2,
QuatArg  inInvInitialOrientation 
)
inline

Calculate properties used during the functions below.

◆ GetTotalLambda()

Vec3 RotationQuatConstraintPart::GetTotalLambda ( ) const
inline

Return lagrange multiplier.

◆ RestoreState()

void RotationQuatConstraintPart::RestoreState ( StateRecorder inStream)
inline

Restore state of this constraint part.

◆ SaveState()

void RotationQuatConstraintPart::SaveState ( StateRecorder inStream) const
inline

Save state of this constraint part.

◆ sGetInvInitialOrientation()

static Quat RotationQuatConstraintPart::sGetInvInitialOrientation ( const Body inBody1,
const Body inBody2 
)
inlinestatic

Return inverse of initial rotation from body 1 to body 2 in body 1 space.

◆ SolvePositionConstraint()

bool RotationQuatConstraintPart::SolvePositionConstraint ( Body ioBody1,
Body ioBody2,
QuatArg  inInvInitialOrientation,
float  inBaumgarte 
) const
inline

Iteratively update the position constraint. Makes sure C(...) = 0.

◆ SolveVelocityConstraint()

bool RotationQuatConstraintPart::SolveVelocityConstraint ( Body ioBody1,
Body ioBody2 
)
inline

Iteratively update the velocity constraint. Makes sure d/dt C(...) = 0, where C is the constraint equation.

◆ WarmStart()

void RotationQuatConstraintPart::WarmStart ( Body ioBody1,
Body ioBody2,
float  inWarmStartImpulseRatio 
)
inline

Must be called from the WarmStartVelocityConstraint call to apply the previous frame's impulses.


The documentation for this class was generated from the following file: