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 Deactivate ()
 Deactivate this constraint. More...
 
bool IsActive () const
 Check if constraint is active. 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.

◆ Deactivate()

void RotationQuatConstraintPart::Deactivate ( )
inline

Deactivate this constraint.

◆ GetTotalLambda()

Vec3 RotationQuatConstraintPart::GetTotalLambda ( ) const
inline

Return lagrange multiplier.

◆ IsActive()

bool RotationQuatConstraintPart::IsActive ( ) const
inline

Check if constraint is active.

◆ 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: