Path: blob/master/thirdparty/jolt_physics/Jolt/Physics/Constraints/PathConstraint.h
9913 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/PathConstraintPath.h>8#include <Jolt/Physics/Constraints/MotorSettings.h>9#include <Jolt/Physics/Constraints/ConstraintPart/AxisConstraintPart.h>10#include <Jolt/Physics/Constraints/ConstraintPart/DualAxisConstraintPart.h>11#include <Jolt/Physics/Constraints/ConstraintPart/HingeRotationConstraintPart.h>12#include <Jolt/Physics/Constraints/ConstraintPart/RotationEulerConstraintPart.h>1314JPH_NAMESPACE_BEGIN1516JPH_SUPPRESS_WARNING_PUSH17JPH_GCC_SUPPRESS_WARNING("-Wshadow") // GCC complains about the 'Free' value conflicting with the 'Free' method1819/// How to constrain the rotation of the body to a PathConstraint20enum class EPathRotationConstraintType21{22Free, ///< Do not constrain the rotation of the body at all23ConstrainAroundTangent, ///< Only allow rotation around the tangent vector (following the path)24ConstrainAroundNormal, ///< Only allow rotation around the normal vector (perpendicular to the path)25ConstrainAroundBinormal, ///< Only allow rotation around the binormal vector (perpendicular to the path)26ConstrainToPath, ///< Fully constrain the rotation of body 2 to the path (following the tangent and normal of the path)27FullyConstrained, ///< Fully constrain the rotation of the body 2 to the rotation of body 128};2930JPH_SUPPRESS_WARNING_POP3132/// Path constraint settings, used to constrain the degrees of freedom between two bodies to a path33///34/// The requirements of the path are that:35/// * Tangent, normal and bi-normal form an orthonormal basis with: tangent cross bi-normal = normal36/// * The path points along the tangent vector37/// * The path is continuous so doesn't contain any sharp corners38///39/// The reason for all this is that the constraint acts like a slider constraint with the sliding axis being the tangent vector (the assumption here is that delta time will be small enough so that the path is linear for that delta time).40class JPH_EXPORT PathConstraintSettings final : public TwoBodyConstraintSettings41{42JPH_DECLARE_SERIALIZABLE_VIRTUAL(JPH_EXPORT, PathConstraintSettings)4344public:45// See: ConstraintSettings::SaveBinaryState46virtual void SaveBinaryState(StreamOut &inStream) const override;4748/// Create an instance of this constraint49virtual TwoBodyConstraint * Create(Body &inBody1, Body &inBody2) const override;5051/// The path that constrains the two bodies52RefConst<PathConstraintPath> mPath;5354/// The position of the path start relative to world transform of body 155Vec3 mPathPosition = Vec3::sZero();5657/// The rotation of the path start relative to world transform of body 158Quat mPathRotation = Quat::sIdentity();5960/// The fraction along the path that corresponds to the initial position of body 2. Usually this is 0, the beginning of the path. But if you want to start an object halfway the path you can calculate this with mPath->GetClosestPoint(point on path to attach body to).61float mPathFraction = 0.0f;6263/// Maximum amount of friction force to apply (N) when not driven by a motor.64float mMaxFrictionForce = 0.0f;6566/// In case the constraint is powered, this determines the motor settings along the path67MotorSettings mPositionMotorSettings;6869/// How to constrain the rotation of the body to the path70EPathRotationConstraintType mRotationConstraintType = EPathRotationConstraintType::Free;7172protected:73// See: ConstraintSettings::RestoreBinaryState74virtual void RestoreBinaryState(StreamIn &inStream) override;75};7677/// Path constraint, used to constrain the degrees of freedom between two bodies to a path78class JPH_EXPORT PathConstraint final : public TwoBodyConstraint79{80public:81JPH_OVERRIDE_NEW_DELETE8283/// Construct point constraint84PathConstraint(Body &inBody1, Body &inBody2, const PathConstraintSettings &inSettings);8586// Generic interface of a constraint87virtual EConstraintSubType GetSubType() const override { return EConstraintSubType::Path; }88virtual void NotifyShapeChanged(const BodyID &inBodyID, Vec3Arg inDeltaCOM) override;89virtual void SetupVelocityConstraint(float inDeltaTime) override;90virtual void ResetWarmStart() override;91virtual void WarmStartVelocityConstraint(float inWarmStartImpulseRatio) override;92virtual bool SolveVelocityConstraint(float inDeltaTime) override;93virtual bool SolvePositionConstraint(float inDeltaTime, float inBaumgarte) override;94#ifdef JPH_DEBUG_RENDERER95virtual void DrawConstraint(DebugRenderer *inRenderer) const override;96#endif // JPH_DEBUG_RENDERER97virtual void SaveState(StateRecorder &inStream) const override;98virtual void RestoreState(StateRecorder &inStream) override;99virtual bool IsActive() const override { return TwoBodyConstraint::IsActive() && mPath != nullptr; }100virtual Ref<ConstraintSettings> GetConstraintSettings() const override;101102// See: TwoBodyConstraint103virtual Mat44 GetConstraintToBody1Matrix() const override { return mPathToBody1; }104virtual Mat44 GetConstraintToBody2Matrix() const override { return mPathToBody2; }105106/// Update the path for this constraint107void SetPath(const PathConstraintPath *inPath, float inPathFraction);108109/// Access to the current path110const PathConstraintPath * GetPath() const { return mPath; }111112/// Access to the current fraction along the path e [0, GetPath()->GetMaxPathFraction()]113float GetPathFraction() const { return mPathFraction; }114115/// Friction control116void SetMaxFrictionForce(float inFrictionForce) { mMaxFrictionForce = inFrictionForce; }117float GetMaxFrictionForce() const { return mMaxFrictionForce; }118119/// Position motor settings120MotorSettings & GetPositionMotorSettings() { return mPositionMotorSettings; }121const MotorSettings & GetPositionMotorSettings() const { return mPositionMotorSettings; }122123// Position motor controls (drives body 2 along the path)124void SetPositionMotorState(EMotorState inState) { JPH_ASSERT(inState == EMotorState::Off || mPositionMotorSettings.IsValid()); mPositionMotorState = inState; }125EMotorState GetPositionMotorState() const { return mPositionMotorState; }126void SetTargetVelocity(float inVelocity) { mTargetVelocity = inVelocity; }127float GetTargetVelocity() const { return mTargetVelocity; }128void SetTargetPathFraction(float inFraction) { JPH_ASSERT(mPath->IsLooping() || (inFraction >= 0.0f && inFraction <= mPath->GetPathMaxFraction())); mTargetPathFraction = inFraction; }129float GetTargetPathFraction() const { return mTargetPathFraction; }130131///@name Get Lagrange multiplier from last physics update (the linear/angular impulse applied to satisfy the constraint)132inline Vector<2> GetTotalLambdaPosition() const { return mPositionConstraintPart.GetTotalLambda(); }133inline float GetTotalLambdaPositionLimits() const { return mPositionLimitsConstraintPart.GetTotalLambda(); }134inline float GetTotalLambdaMotor() const { return mPositionMotorConstraintPart.GetTotalLambda(); }135inline Vector<2> GetTotalLambdaRotationHinge() const { return mHingeConstraintPart.GetTotalLambda(); }136inline Vec3 GetTotalLambdaRotation() const { return mRotationConstraintPart.GetTotalLambda(); }137138private:139// Internal helper function to calculate the values below140void CalculateConstraintProperties(float inDeltaTime);141142// CONFIGURATION PROPERTIES FOLLOW143144RefConst<PathConstraintPath> mPath; ///< The path that attaches the two bodies145Mat44 mPathToBody1; ///< Transform that takes a quantity from path space to body 1 center of mass space146Mat44 mPathToBody2; ///< Transform that takes a quantity from path space to body 2 center of mass space147EPathRotationConstraintType mRotationConstraintType; ///< How to constrain the rotation of the path148149// Friction150float mMaxFrictionForce;151152// Motor controls153MotorSettings mPositionMotorSettings;154EMotorState mPositionMotorState = EMotorState::Off;155float mTargetVelocity = 0.0f;156float mTargetPathFraction = 0.0f;157158// RUN TIME PROPERTIES FOLLOW159160// Positions where the point constraint acts on in world space161Vec3 mR1;162Vec3 mR2;163164// X2 + R2 - X1 - R1165Vec3 mU;166167// World space path tangent168Vec3 mPathTangent;169170// Normals to the path tangent171Vec3 mPathNormal;172Vec3 mPathBinormal;173174// Inverse of initial rotation from body 1 to body 2 in body 1 space (only used when rotation constraint type is FullyConstrained)175Quat mInvInitialOrientation;176177// Current fraction along the path where body 2 is attached178float mPathFraction = 0.0f;179180// Translation constraint parts181DualAxisConstraintPart mPositionConstraintPart; ///< Constraint part that keeps the movement along the tangent of the path182AxisConstraintPart mPositionLimitsConstraintPart; ///< Constraint part that prevents movement beyond the beginning and end of the path183AxisConstraintPart mPositionMotorConstraintPart; ///< Constraint to drive the object along the path or to apply friction184185// Rotation constraint parts186HingeRotationConstraintPart mHingeConstraintPart; ///< Constraint part that removes 2 degrees of rotation freedom187RotationEulerConstraintPart mRotationConstraintPart; ///< Constraint part that removes all rotational freedom188};189190JPH_NAMESPACE_END191192193