123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
- // SPDX-License-Identifier: MIT
- #pragma once
- #include <Physics/Constraints/TwoBodyConstraint.h>
- #include <Physics/Constraints/MotorSettings.h>
- #include <Physics/Constraints/ConstraintPart/PointConstraintPart.h>
- #include <Physics/Constraints/ConstraintPart/HingeRotationConstraintPart.h>
- #include <Physics/Constraints/ConstraintPart/AngleConstraintPart.h>
- namespace JPH {
- /// Hinge constraint settings, used to create a hinge constraint
- class HingeConstraintSettings final : public TwoBodyConstraintSettings
- {
- public:
- JPH_DECLARE_SERIALIZABLE_VIRTUAL(HingeConstraintSettings)
- // See: ConstraintSettings::SaveBinaryState
- virtual void SaveBinaryState(StreamOut &inStream) const override;
- /// Create an an instance of this constraint
- virtual TwoBodyConstraint * Create(Body &inBody1, Body &inBody2) const override;
- /// Body 1 constraint reference frame (in world space).
- /// Hinge axis is the axis where rotation is allowed, normal axis defines the 0 angle of the hinge.
- Vec3 mPoint1 = Vec3::sZero();
- Vec3 mHingeAxis1 = Vec3::sAxisY();
- Vec3 mNormalAxis1 = Vec3::sAxisX();
-
- /// Body 2 constraint reference frame (in world space)
- Vec3 mPoint2 = Vec3::sZero();
- Vec3 mHingeAxis2 = Vec3::sAxisY();
- Vec3 mNormalAxis2 = Vec3::sAxisX();
-
- /// Bodies are assumed to be placed so that the hinge angle = 0, movement will be limited between [mLimitsMin, mLimitsMax] where mLimitsMin e [-pi, 0] and mLimitsMax e [0, pi].
- /// Both angles are in radians.
- float mLimitsMin = -JPH_PI;
- float mLimitsMax = JPH_PI;
- /// Maximum amount of torque (N m) to apply as friction when the constraint is not powered by a motor
- float mMaxFrictionTorque = 0.0f;
- /// In case the constraint is powered, this determines the motor settings around the hinge axis
- MotorSettings mMotorSettings;
- protected:
- // See: ConstraintSettings::RestoreBinaryState
- virtual void RestoreBinaryState(StreamIn &inStream) override;
- };
- /// A hinge constraint constrains 2 bodies on a single point and allows only a single axis of rotation
- class HingeConstraint final : public TwoBodyConstraint
- {
- public:
- /// Construct hinge constraint
- HingeConstraint(Body &inBody1, Body &inBody2, const HingeConstraintSettings &inSettings);
- // Generic interface of a constraint
- virtual EConstraintType GetType() const override { return EConstraintType::Hinge; }
- virtual void SetupVelocityConstraint(float inDeltaTime) override;
- virtual void WarmStartVelocityConstraint(float inWarmStartImpulseRatio) override;
- virtual bool SolveVelocityConstraint(float inDeltaTime) override;
- virtual bool SolvePositionConstraint(float inDeltaTime, float inBaumgarte) override;
- #ifdef JPH_DEBUG_RENDERER
- virtual void DrawConstraint(DebugRenderer *inRenderer) const override;
- virtual void DrawConstraintLimits(DebugRenderer *inRenderer) const override;
- #endif // JPH_DEBUG_RENDERER
- virtual void SaveState(StateRecorder &inStream) const override;
- virtual void RestoreState(StateRecorder &inStream) override;
- // See: TwoBodyConstraint
- virtual Mat44 GetConstraintToBody1Matrix() const override;
- virtual Mat44 GetConstraintToBody2Matrix() const override;
- // Friction control
- void SetMaxFrictionTorque(float inFrictionTorque) { mMaxFrictionTorque = inFrictionTorque; }
- float GetMaxFrictionTorque() const { return mMaxFrictionTorque; }
- // Motor settings
- MotorSettings & GetMotorSettings() { return mMotorSettings; }
- const MotorSettings & GetMotorSettings() const { return mMotorSettings; }
- // Motor controls
- void SetMotorState(EMotorState inState) { JPH_ASSERT(inState == EMotorState::Off || mMotorSettings.IsValid()); mMotorState = inState; }
- EMotorState GetMotorState() const { return mMotorState; }
- void SetTargetAngularVelocity(float inAngularVelocity) { mTargetAngularVelocity = inAngularVelocity; } ///< rad/s
- float GetTargetAngularVelocity() const { return mTargetAngularVelocity; }
- void SetTargetAngle(float inAngle) { mTargetAngle = mHasLimits? Clamp(inAngle, mLimitsMin, mLimitsMax) : inAngle; } ///< rad
- float GetTargetAngle() const { return mTargetAngle; }
- /// Update the rotation limits of the hinge, value in radians (see HingeConstraintSettings)
- void SetLimits(float inLimitsMin, float inLimitsMax);
- float GetLimitsMin() const { return mLimitsMin; }
- float GetLimitsMax() const { return mLimitsMax; }
- bool HasLimits() const { return mHasLimits; }
- ///@name Get Lagrange multiplier from last physics update (relates to how much force/torque was applied to satisfy the constraint)
- inline Vec3 GetTotalLambdaPosition() const { return mPointConstraintPart.GetTotalLambda(); }
- inline Vector<2> GetTotalLambdaRotation() const { return mRotationConstraintPart.GetTotalLambda(); }
- inline float GetTotalLambdaRotationLimits() const { return mRotationLimitsConstraintPart.GetTotalLambda(); }
- inline float GetTotalLambdaMotor() const { return mMotorConstraintPart.GetTotalLambda(); }
- private:
- // Internal helper function to calculate the values below
- void CalculateA1AndTheta();
- void CalculateRotationLimitsConstraintProperties(float inDeltaTime);
- void CalculateMotorConstraintProperties(float inDeltaTime);
- inline float GetSmallestAngleToLimit() const;
- // CONFIGURATION PROPERTIES FOLLOW
- // Local space constraint positions
- Vec3 mLocalSpacePosition1;
- Vec3 mLocalSpacePosition2;
- // Local space hinge directions
- Vec3 mLocalSpaceHingeAxis1;
- Vec3 mLocalSpaceHingeAxis2;
- // Local space normal direction (direction relative to which to draw constraint limits)
- Vec3 mLocalSpaceNormalAxis1;
- Vec3 mLocalSpaceNormalAxis2;
-
- // Inverse of initial relative orientation between bodies (which defines hinge angle = 0)
- Quat mInvInitialOrientation;
- // Hinge limits
- bool mHasLimits;
- float mLimitsMin;
- float mLimitsMax;
- // Friction
- float mMaxFrictionTorque;
- // Motor controls
- MotorSettings mMotorSettings;
- EMotorState mMotorState = EMotorState::Off;
- float mTargetAngularVelocity = 0.0f;
- float mTargetAngle = 0.0f;
- // RUN TIME PROPERTIES FOLLOW
- // Current rotation around the hinge axis
- float mTheta = 0.0f;
-
- // World space hinge axis for body 1
- Vec3 mA1;
- // The constraint parts
- PointConstraintPart mPointConstraintPart;
- HingeRotationConstraintPart mRotationConstraintPart;
- AngleConstraintPart mRotationLimitsConstraintPart;
- AngleConstraintPart mMotorConstraintPart;
- };
- } // JPH
|