Path: blob/master/thirdparty/jolt_physics/Jolt/Physics/Constraints/Constraint.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/Core/Reference.h>7#include <Jolt/Core/NonCopyable.h>8#include <Jolt/Core/Result.h>9#include <Jolt/ObjectStream/SerializableObject.h>1011JPH_NAMESPACE_BEGIN1213class BodyID;14class IslandBuilder;15class LargeIslandSplitter;16class BodyManager;17class StateRecorder;18class StreamIn;19class StreamOut;20#ifdef JPH_DEBUG_RENDERER21class DebugRenderer;22#endif // JPH_DEBUG_RENDERER2324/// Enum to identify constraint type25enum class EConstraintType26{27Constraint,28TwoBodyConstraint,29};3031/// Enum to identify constraint sub type32enum class EConstraintSubType33{34Fixed,35Point,36Hinge,37Slider,38Distance,39Cone,40SwingTwist,41SixDOF,42Path,43Vehicle,44RackAndPinion,45Gear,46Pulley,4748/// User defined constraint types start here49User1,50User2,51User3,52User453};5455/// Certain constraints support setting them up in local or world space. This governs what is used.56enum class EConstraintSpace57{58LocalToBodyCOM, ///< All constraint properties are specified in local space to center of mass of the bodies that are being constrained (so e.g. 'constraint position 1' will be local to body 1 COM, 'constraint position 2' will be local to body 2 COM). Note that this means you need to subtract Shape::GetCenterOfMass() from positions!59WorldSpace, ///< All constraint properties are specified in world space60};6162/// Class used to store the configuration of a constraint. Allows run-time creation of constraints.63class JPH_EXPORT ConstraintSettings : public SerializableObject, public RefTarget<ConstraintSettings>64{65JPH_DECLARE_SERIALIZABLE_VIRTUAL(JPH_EXPORT, ConstraintSettings)6667public:68using ConstraintResult = Result<Ref<ConstraintSettings>>;6970/// Saves the contents of the constraint settings in binary form to inStream.71virtual void SaveBinaryState(StreamOut &inStream) const;7273/// Creates a constraint of the correct type and restores its contents from the binary stream inStream.74static ConstraintResult sRestoreFromBinaryState(StreamIn &inStream);7576/// If this constraint is enabled initially. Use Constraint::SetEnabled to toggle after creation.77bool mEnabled = true;7879/// Priority of the constraint when solving. Higher numbers have are more likely to be solved correctly.80/// Note that if you want a deterministic simulation and you cannot guarantee the order in which constraints are added/removed, you can make the priority for all constraints unique to get a deterministic ordering.81uint32 mConstraintPriority = 0;8283/// Used only when the constraint is active. Override for the number of solver velocity iterations to run, 0 means use the default in PhysicsSettings::mNumVelocitySteps. The number of iterations to use is the max of all contacts and constraints in the island.84uint mNumVelocityStepsOverride = 0;8586/// Used only when the constraint is active. Override for the number of solver position iterations to run, 0 means use the default in PhysicsSettings::mNumPositionSteps. The number of iterations to use is the max of all contacts and constraints in the island.87uint mNumPositionStepsOverride = 0;8889/// Size of constraint when drawing it through the debug renderer90float mDrawConstraintSize = 1.0f;9192/// User data value (can be used by application)93uint64 mUserData = 0;9495protected:96/// This function should not be called directly, it is used by sRestoreFromBinaryState.97virtual void RestoreBinaryState(StreamIn &inStream);98};99100/// Base class for all physics constraints. A constraint removes one or more degrees of freedom for a rigid body.101class JPH_EXPORT Constraint : public RefTarget<Constraint>, public NonCopyable102{103public:104JPH_OVERRIDE_NEW_DELETE105106/// Constructor107explicit Constraint(const ConstraintSettings &inSettings) :108#ifdef JPH_DEBUG_RENDERER109mDrawConstraintSize(inSettings.mDrawConstraintSize),110#endif // JPH_DEBUG_RENDERER111mConstraintPriority(inSettings.mConstraintPriority),112mNumVelocityStepsOverride(uint8(inSettings.mNumVelocityStepsOverride)),113mNumPositionStepsOverride(uint8(inSettings.mNumPositionStepsOverride)),114mEnabled(inSettings.mEnabled),115mUserData(inSettings.mUserData)116{117JPH_ASSERT(inSettings.mNumVelocityStepsOverride < 256);118JPH_ASSERT(inSettings.mNumPositionStepsOverride < 256);119}120121/// Virtual destructor122virtual ~Constraint() = default;123124/// Get the type of a constraint125virtual EConstraintType GetType() const { return EConstraintType::Constraint; }126127/// Get the sub type of a constraint128virtual EConstraintSubType GetSubType() const = 0;129130/// Priority of the constraint when solving. Higher numbers have are more likely to be solved correctly.131/// Note that if you want a deterministic simulation and you cannot guarantee the order in which constraints are added/removed, you can make the priority for all constraints unique to get a deterministic ordering.132uint32 GetConstraintPriority() const { return mConstraintPriority; }133void SetConstraintPriority(uint32 inPriority) { mConstraintPriority = inPriority; }134135/// Used only when the constraint is active. Override for the number of solver velocity iterations to run, 0 means use the default in PhysicsSettings::mNumVelocitySteps. The number of iterations to use is the max of all contacts and constraints in the island.136void SetNumVelocityStepsOverride(uint inN) { JPH_ASSERT(inN < 256); mNumVelocityStepsOverride = uint8(inN); }137uint GetNumVelocityStepsOverride() const { return mNumVelocityStepsOverride; }138139/// Used only when the constraint is active. Override for the number of solver position iterations to run, 0 means use the default in PhysicsSettings::mNumPositionSteps. The number of iterations to use is the max of all contacts and constraints in the island.140void SetNumPositionStepsOverride(uint inN) { JPH_ASSERT(inN < 256); mNumPositionStepsOverride = uint8(inN); }141uint GetNumPositionStepsOverride() const { return mNumPositionStepsOverride; }142143/// Enable / disable this constraint. This can e.g. be used to implement a breakable constraint by detecting that the constraint impulse144/// (see e.g. PointConstraint::GetTotalLambdaPosition) went over a certain limit and then disabling the constraint.145/// Note that although a disabled constraint will not affect the simulation in any way anymore, it does incur some processing overhead.146/// Alternatively you can remove a constraint from the constraint manager (which may be more costly if you want to disable the constraint for a short while).147void SetEnabled(bool inEnabled) { mEnabled = inEnabled; }148149/// Test if a constraint is enabled.150bool GetEnabled() const { return mEnabled; }151152/// Access to the user data, can be used for anything by the application153uint64 GetUserData() const { return mUserData; }154void SetUserData(uint64 inUserData) { mUserData = inUserData; }155156/// Notify the constraint that the shape of a body has changed and that its center of mass has moved by inDeltaCOM.157/// Bodies don't know which constraints are connected to them so the user is responsible for notifying the relevant constraints when a body changes.158/// @param inBodyID ID of the body that has changed159/// @param inDeltaCOM The delta of the center of mass of the body (shape->GetCenterOfMass() - shape_before_change->GetCenterOfMass())160virtual void NotifyShapeChanged(const BodyID &inBodyID, Vec3Arg inDeltaCOM) = 0;161162/// Notify the system that the configuration of the bodies and/or constraint has changed enough so that the warm start impulses should not be applied the next frame.163/// You can use this function for example when repositioning a ragdoll through Ragdoll::SetPose in such a way that the orientation of the bodies completely changes so that164/// the previous frame impulses are no longer a good approximation of what the impulses will be in the next frame. Calling this function when there are no big changes165/// will result in the constraints being much 'softer' than usual so they are more easily violated (e.g. a long chain of bodies might sag a bit if you call this every frame).166virtual void ResetWarmStart() = 0;167168///@name Solver interface169///@{170virtual bool IsActive() const { return mEnabled; }171virtual void SetupVelocityConstraint(float inDeltaTime) = 0;172virtual void WarmStartVelocityConstraint(float inWarmStartImpulseRatio) = 0;173virtual bool SolveVelocityConstraint(float inDeltaTime) = 0;174virtual bool SolvePositionConstraint(float inDeltaTime, float inBaumgarte) = 0;175///@}176177/// Link bodies that are connected by this constraint in the island builder178virtual void BuildIslands(uint32 inConstraintIndex, IslandBuilder &ioBuilder, BodyManager &inBodyManager) = 0;179180/// Link bodies that are connected by this constraint in the same split. Returns the split index.181virtual uint BuildIslandSplits(LargeIslandSplitter &ioSplitter) const = 0;182183#ifdef JPH_DEBUG_RENDERER184// Drawing interface185virtual void DrawConstraint(DebugRenderer *inRenderer) const = 0;186virtual void DrawConstraintLimits([[maybe_unused]] DebugRenderer *inRenderer) const { }187virtual void DrawConstraintReferenceFrame([[maybe_unused]] DebugRenderer *inRenderer) const { }188189/// Size of constraint when drawing it through the debug renderer190float GetDrawConstraintSize() const { return mDrawConstraintSize; }191void SetDrawConstraintSize(float inSize) { mDrawConstraintSize = inSize; }192#endif // JPH_DEBUG_RENDERER193194/// Saving state for replay195virtual void SaveState(StateRecorder &inStream) const;196197/// Restoring state for replay198virtual void RestoreState(StateRecorder &inStream);199200/// Debug function to convert a constraint to its settings, note that this will not save to which bodies the constraint is connected to201virtual Ref<ConstraintSettings> GetConstraintSettings() const = 0;202203protected:204/// Helper function to copy settings back to constraint settings for this base class205void ToConstraintSettings(ConstraintSettings &outSettings) const;206207#ifdef JPH_DEBUG_RENDERER208/// Size of constraint when drawing it through the debug renderer209float mDrawConstraintSize;210#endif // JPH_DEBUG_RENDERER211212private:213friend class ConstraintManager;214215/// Index that indicates this constraint is not in the constraint manager216static constexpr uint32 cInvalidConstraintIndex = 0xffffffff;217218/// Index in the mConstraints list of the ConstraintManager for easy finding219uint32 mConstraintIndex = cInvalidConstraintIndex;220221/// Priority of the constraint when solving. Higher numbers have are more likely to be solved correctly.222uint32 mConstraintPriority = 0;223224/// Used only when the constraint is active. Override for the number of solver velocity iterations to run, 0 means use the default in PhysicsSettings::mNumVelocitySteps. The number of iterations to use is the max of all contacts and constraints in the island.225uint8 mNumVelocityStepsOverride = 0;226227/// Used only when the constraint is active. Override for the number of solver position iterations to run, 0 means use the default in PhysicsSettings::mNumPositionSteps. The number of iterations to use is the max of all contacts and constraints in the island.228uint8 mNumPositionStepsOverride = 0;229230/// If this constraint is currently enabled231bool mEnabled = true;232233/// User data value (can be used by application)234uint64 mUserData;235};236237JPH_NAMESPACE_END238239240