Path: blob/master/thirdparty/jolt_physics/Jolt/Physics/Constraints/SixDOFConstraint.h
9912 views
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)1// SPDX-FileCopyrightText: 2021 Jorrit Rouwe2// SPDX-License-Identifier: MIT34#pragma once56#include <Jolt/Physics/Constraints/TwoBodyConstraint.h>7#include <Jolt/Physics/Constraints/MotorSettings.h>8#include <Jolt/Physics/Constraints/ConstraintPart/PointConstraintPart.h>9#include <Jolt/Physics/Constraints/ConstraintPart/AxisConstraintPart.h>10#include <Jolt/Physics/Constraints/ConstraintPart/AngleConstraintPart.h>11#include <Jolt/Physics/Constraints/ConstraintPart/RotationEulerConstraintPart.h>12#include <Jolt/Physics/Constraints/ConstraintPart/SwingTwistConstraintPart.h>1314JPH_NAMESPACE_BEGIN1516/// 6 Degree Of Freedom Constraint setup structure. Allows control over each of the 6 degrees of freedom.17class JPH_EXPORT SixDOFConstraintSettings final : public TwoBodyConstraintSettings18{19JPH_DECLARE_SERIALIZABLE_VIRTUAL(JPH_EXPORT, SixDOFConstraintSettings)2021public:22/// Constraint is split up into translation/rotation around X, Y and Z axis.23enum EAxis24{25TranslationX,26TranslationY,27TranslationZ,2829RotationX,30RotationY,31RotationZ,3233Num,34NumTranslation = TranslationZ + 1,35};3637// See: ConstraintSettings::SaveBinaryState38virtual void SaveBinaryState(StreamOut &inStream) const override;3940/// Create an instance of this constraint41virtual TwoBodyConstraint * Create(Body &inBody1, Body &inBody2) const override;4243/// This determines in which space the constraint is setup, all properties below should be in the specified space44EConstraintSpace mSpace = EConstraintSpace::WorldSpace;4546/// Body 1 constraint reference frame (space determined by mSpace)47RVec3 mPosition1 = RVec3::sZero();48Vec3 mAxisX1 = Vec3::sAxisX();49Vec3 mAxisY1 = Vec3::sAxisY();5051/// Body 2 constraint reference frame (space determined by mSpace)52RVec3 mPosition2 = RVec3::sZero();53Vec3 mAxisX2 = Vec3::sAxisX();54Vec3 mAxisY2 = Vec3::sAxisY();5556/// Friction settings.57/// For translation: Max friction force in N. 0 = no friction.58/// For rotation: Max friction torque in Nm. 0 = no friction.59float mMaxFriction[EAxis::Num] = { 0, 0, 0, 0, 0, 0 };6061/// The type of swing constraint that we want to use.62ESwingType mSwingType = ESwingType::Cone;6364/// Limits.65/// For translation: Min and max linear limits in m (0 is frame of body 1 and 2 coincide).66/// For rotation: Min and max angular limits in rad (0 is frame of body 1 and 2 coincide). See comments at Axis enum for limit ranges.67///68/// Remove degree of freedom by setting min = FLT_MAX and max = -FLT_MAX. The constraint will be driven to 0 for this axis.69///70/// Free movement over an axis is allowed when min = -FLT_MAX and max = FLT_MAX.71///72/// Rotation limit around X-Axis: When limited, should be \f$\in [-\pi, \pi]\f$. Can be asymmetric around zero.73///74/// Rotation limit around Y-Z Axis: Forms a pyramid or cone shaped limit:75/// * For pyramid, should be \f$\in [-\pi, \pi]\f$ and does not need to be symmetrical around zero.76/// * For cone should be \f$\in [0, \pi]\f$ and needs to be symmetrical around zero (min limit is assumed to be -max limit).77float mLimitMin[EAxis::Num] = { -FLT_MAX, -FLT_MAX, -FLT_MAX, -FLT_MAX, -FLT_MAX, -FLT_MAX };78float mLimitMax[EAxis::Num] = { FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX };7980/// When enabled, this makes the limits soft. When the constraint exceeds the limits, a spring force will pull it back.81/// Only soft translation limits are supported, soft rotation limits are not currently supported.82SpringSettings mLimitsSpringSettings[EAxis::NumTranslation];8384/// Make axis free (unconstrained)85void MakeFreeAxis(EAxis inAxis) { mLimitMin[inAxis] = -FLT_MAX; mLimitMax[inAxis] = FLT_MAX; }86bool IsFreeAxis(EAxis inAxis) const { return mLimitMin[inAxis] == -FLT_MAX && mLimitMax[inAxis] == FLT_MAX; }8788/// Make axis fixed (fixed at value 0)89void MakeFixedAxis(EAxis inAxis) { mLimitMin[inAxis] = FLT_MAX; mLimitMax[inAxis] = -FLT_MAX; }90bool IsFixedAxis(EAxis inAxis) const { return mLimitMin[inAxis] >= mLimitMax[inAxis]; }9192/// Set a valid range for the constraint (if inMax < inMin, the axis will become fixed)93void SetLimitedAxis(EAxis inAxis, float inMin, float inMax) { mLimitMin[inAxis] = inMin; mLimitMax[inAxis] = inMax; }9495/// Motor settings for each axis96MotorSettings mMotorSettings[EAxis::Num];9798protected:99// See: ConstraintSettings::RestoreBinaryState100virtual void RestoreBinaryState(StreamIn &inStream) override;101};102103/// 6 Degree Of Freedom Constraint. Allows control over each of the 6 degrees of freedom.104class JPH_EXPORT SixDOFConstraint final : public TwoBodyConstraint105{106public:107JPH_OVERRIDE_NEW_DELETE108109/// Get Axis from settings class110using EAxis = SixDOFConstraintSettings::EAxis;111112/// Construct six DOF constraint113SixDOFConstraint(Body &inBody1, Body &inBody2, const SixDOFConstraintSettings &inSettings);114115/// Generic interface of a constraint116virtual EConstraintSubType GetSubType() const override { return EConstraintSubType::SixDOF; }117virtual void NotifyShapeChanged(const BodyID &inBodyID, Vec3Arg inDeltaCOM) override;118virtual void SetupVelocityConstraint(float inDeltaTime) override;119virtual void ResetWarmStart() override;120virtual void WarmStartVelocityConstraint(float inWarmStartImpulseRatio) override;121virtual bool SolveVelocityConstraint(float inDeltaTime) override;122virtual bool SolvePositionConstraint(float inDeltaTime, float inBaumgarte) override;123#ifdef JPH_DEBUG_RENDERER124virtual void DrawConstraint(DebugRenderer *inRenderer) const override;125virtual void DrawConstraintLimits(DebugRenderer *inRenderer) const override;126#endif // JPH_DEBUG_RENDERER127virtual void SaveState(StateRecorder &inStream) const override;128virtual void RestoreState(StateRecorder &inStream) override;129virtual Ref<ConstraintSettings> GetConstraintSettings() const override;130131// See: TwoBodyConstraint132virtual Mat44 GetConstraintToBody1Matrix() const override { return Mat44::sRotationTranslation(mConstraintToBody1, mLocalSpacePosition1); }133virtual Mat44 GetConstraintToBody2Matrix() const override { return Mat44::sRotationTranslation(mConstraintToBody2, mLocalSpacePosition2); }134135/// Update the translation limits for this constraint136void SetTranslationLimits(Vec3Arg inLimitMin, Vec3Arg inLimitMax);137138/// Update the rotational limits for this constraint139void SetRotationLimits(Vec3Arg inLimitMin, Vec3Arg inLimitMax);140141/// Get constraint Limits142float GetLimitsMin(EAxis inAxis) const { return mLimitMin[inAxis]; }143float GetLimitsMax(EAxis inAxis) const { return mLimitMax[inAxis]; }144Vec3 GetTranslationLimitsMin() const { return Vec3::sLoadFloat3Unsafe(*reinterpret_cast<const Float3 *>(&mLimitMin[EAxis::TranslationX])); }145Vec3 GetTranslationLimitsMax() const { return Vec3::sLoadFloat3Unsafe(*reinterpret_cast<const Float3 *>(&mLimitMax[EAxis::TranslationX])); }146Vec3 GetRotationLimitsMin() const { return Vec3::sLoadFloat3Unsafe(*reinterpret_cast<const Float3 *>(&mLimitMin[EAxis::RotationX])); }147Vec3 GetRotationLimitsMax() const { return Vec3::sLoadFloat3Unsafe(*reinterpret_cast<const Float3 *>(&mLimitMax[EAxis::RotationX])); }148149/// Check which axis are fixed/free150inline bool IsFixedAxis(EAxis inAxis) const { return (mFixedAxis & (1 << inAxis)) != 0; }151inline bool IsFreeAxis(EAxis inAxis) const { return (mFreeAxis & (1 << inAxis)) != 0; }152153/// Update the limits spring settings154const SpringSettings & GetLimitsSpringSettings(EAxis inAxis) const { JPH_ASSERT(inAxis < EAxis::NumTranslation); return mLimitsSpringSettings[inAxis]; }155void SetLimitsSpringSettings(EAxis inAxis, const SpringSettings& inLimitsSpringSettings) { JPH_ASSERT(inAxis < EAxis::NumTranslation); mLimitsSpringSettings[inAxis] = inLimitsSpringSettings; CacheHasSpringLimits(); }156157/// Set the max friction for each axis158void SetMaxFriction(EAxis inAxis, float inFriction);159float GetMaxFriction(EAxis inAxis) const { return mMaxFriction[inAxis]; }160161/// Get rotation of constraint in constraint space162Quat GetRotationInConstraintSpace() const;163164/// Motor settings165MotorSettings & GetMotorSettings(EAxis inAxis) { return mMotorSettings[inAxis]; }166const MotorSettings & GetMotorSettings(EAxis inAxis) const { return mMotorSettings[inAxis]; }167168/// Motor controls.169/// Translation motors work in constraint space of body 1.170/// Rotation motors work in constraint space of body 2 (!).171void SetMotorState(EAxis inAxis, EMotorState inState);172EMotorState GetMotorState(EAxis inAxis) const { return mMotorState[inAxis]; }173174/// Set the target velocity in body 1 constraint space175Vec3 GetTargetVelocityCS() const { return mTargetVelocity; }176void SetTargetVelocityCS(Vec3Arg inVelocity) { mTargetVelocity = inVelocity; }177178/// Set the target angular velocity in body 2 constraint space (!)179void SetTargetAngularVelocityCS(Vec3Arg inAngularVelocity) { mTargetAngularVelocity = inAngularVelocity; }180Vec3 GetTargetAngularVelocityCS() const { return mTargetAngularVelocity; }181182/// Set the target position in body 1 constraint space183Vec3 GetTargetPositionCS() const { return mTargetPosition; }184void SetTargetPositionCS(Vec3Arg inPosition) { mTargetPosition = inPosition; }185186/// Set the target orientation in body 1 constraint space187void SetTargetOrientationCS(QuatArg inOrientation);188Quat GetTargetOrientationCS() const { return mTargetOrientation; }189190/// Set the target orientation in body space (R2 = R1 * inOrientation, where R1 and R2 are the world space rotations for body 1 and 2).191/// Solve: R2 * ConstraintToBody2 = R1 * ConstraintToBody1 * q (see SwingTwistConstraint::GetSwingTwist) and R2 = R1 * inOrientation for q.192void SetTargetOrientationBS(QuatArg inOrientation) { SetTargetOrientationCS(mConstraintToBody1.Conjugated() * inOrientation * mConstraintToBody2); }193194///@name Get Lagrange multiplier from last physics update (the linear/angular impulse applied to satisfy the constraint)195inline Vec3 GetTotalLambdaPosition() const { return IsTranslationFullyConstrained()? mPointConstraintPart.GetTotalLambda() : Vec3(mTranslationConstraintPart[0].GetTotalLambda(), mTranslationConstraintPart[1].GetTotalLambda(), mTranslationConstraintPart[2].GetTotalLambda()); }196inline Vec3 GetTotalLambdaRotation() const { return IsRotationFullyConstrained()? mRotationConstraintPart.GetTotalLambda() : Vec3(mSwingTwistConstraintPart.GetTotalTwistLambda(), mSwingTwistConstraintPart.GetTotalSwingYLambda(), mSwingTwistConstraintPart.GetTotalSwingZLambda()); }197inline Vec3 GetTotalLambdaMotorTranslation() const { return Vec3(mMotorTranslationConstraintPart[0].GetTotalLambda(), mMotorTranslationConstraintPart[1].GetTotalLambda(), mMotorTranslationConstraintPart[2].GetTotalLambda()); }198inline Vec3 GetTotalLambdaMotorRotation() const { return Vec3(mMotorRotationConstraintPart[0].GetTotalLambda(), mMotorRotationConstraintPart[1].GetTotalLambda(), mMotorRotationConstraintPart[2].GetTotalLambda()); }199200private:201// Calculate properties needed for the position constraint202inline void GetPositionConstraintProperties(Vec3 &outR1PlusU, Vec3 &outR2, Vec3 &outU) const;203204// Sanitize the translation limits205inline void UpdateTranslationLimits();206207// Propagate the rotation limits to the constraint part208inline void UpdateRotationLimits();209210// Update the cached state of which axis are free and which ones are fixed211inline void UpdateFixedFreeAxis();212213// Cache the state of mTranslationMotorActive214void CacheTranslationMotorActive();215216// Cache the state of mRotationMotorActive217void CacheRotationMotorActive();218219// Cache the state of mRotationPositionMotorActive220void CacheRotationPositionMotorActive();221222/// Cache the state of mHasSpringLimits223void CacheHasSpringLimits();224225// Constraint settings helper functions226inline bool IsTranslationConstrained() const { return (mFreeAxis & 0b111) != 0b111; }227inline bool IsTranslationFullyConstrained() const { return (mFixedAxis & 0b111) == 0b111 && !mHasSpringLimits; }228inline bool IsRotationConstrained() const { return (mFreeAxis & 0b111000) != 0b111000; }229inline bool IsRotationFullyConstrained() const { return (mFixedAxis & 0b111000) == 0b111000; }230inline bool HasFriction(EAxis inAxis) const { return !IsFixedAxis(inAxis) && mMaxFriction[inAxis] > 0.0f; }231232// CONFIGURATION PROPERTIES FOLLOW233234// Local space constraint positions235Vec3 mLocalSpacePosition1;236Vec3 mLocalSpacePosition2;237238// Transforms from constraint space to body space239Quat mConstraintToBody1;240Quat mConstraintToBody2;241242// Limits243uint8 mFreeAxis = 0; // Bitmask of free axis (bit 0 = TranslationX)244uint8 mFixedAxis = 0; // Bitmask of fixed axis (bit 0 = TranslationX)245bool mTranslationMotorActive = false; // If any of the translational frictions / motors are active246bool mRotationMotorActive = false; // If any of the rotational frictions / motors are active247uint8 mRotationPositionMotorActive = 0; // Bitmask of axis that have position motor active (bit 0 = RotationX)248bool mHasSpringLimits = false; // If any of the limit springs have a non-zero frequency/stiffness249float mLimitMin[EAxis::Num];250float mLimitMax[EAxis::Num];251SpringSettings mLimitsSpringSettings[EAxis::NumTranslation];252253// Motor settings for each axis254MotorSettings mMotorSettings[EAxis::Num];255256// Friction settings for each axis257float mMaxFriction[EAxis::Num];258259// Motor controls260EMotorState mMotorState[EAxis::Num] = { EMotorState::Off, EMotorState::Off, EMotorState::Off, EMotorState::Off, EMotorState::Off, EMotorState::Off };261Vec3 mTargetVelocity = Vec3::sZero();262Vec3 mTargetAngularVelocity = Vec3::sZero();263Vec3 mTargetPosition = Vec3::sZero();264Quat mTargetOrientation = Quat::sIdentity();265266// RUN TIME PROPERTIES FOLLOW267268// Constraint space axis in world space269Vec3 mTranslationAxis[3];270Vec3 mRotationAxis[3];271272// Translation displacement (valid when translation axis has a range limit)273float mDisplacement[3];274275// Individual constraint parts for translation, or a combined point constraint part if all axis are fixed276AxisConstraintPart mTranslationConstraintPart[3];277PointConstraintPart mPointConstraintPart;278279// Individual constraint parts for rotation or a combined constraint part if rotation is fixed280SwingTwistConstraintPart mSwingTwistConstraintPart;281RotationEulerConstraintPart mRotationConstraintPart;282283// Motor or friction constraints284AxisConstraintPart mMotorTranslationConstraintPart[3];285AngleConstraintPart mMotorRotationConstraintPart[3];286};287288JPH_NAMESPACE_END289290291