Path: blob/master/thirdparty/jolt_physics/Jolt/Physics/Constraints/Constraint.h
22061 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/// Don't allow (copy) constructing this base class, but allow derived classes to (copy) construct themselves97ConstraintSettings() = default;98ConstraintSettings(const ConstraintSettings &) = default;99ConstraintSettings & operator = (const ConstraintSettings &) = default;100101/// This function should not be called directly, it is used by sRestoreFromBinaryState.102virtual void RestoreBinaryState(StreamIn &inStream);103};104105/// Base class for all physics constraints. A constraint removes one or more degrees of freedom for a rigid body.106class JPH_EXPORT Constraint : public RefTarget<Constraint>, public NonCopyable107{108public:109JPH_OVERRIDE_NEW_DELETE110111/// Constructor112explicit Constraint(const ConstraintSettings &inSettings) :113#ifdef JPH_DEBUG_RENDERER114mDrawConstraintSize(inSettings.mDrawConstraintSize),115#endif // JPH_DEBUG_RENDERER116mConstraintPriority(inSettings.mConstraintPriority),117mNumVelocityStepsOverride(uint8(inSettings.mNumVelocityStepsOverride)),118mNumPositionStepsOverride(uint8(inSettings.mNumPositionStepsOverride)),119mEnabled(inSettings.mEnabled),120mUserData(inSettings.mUserData)121{122JPH_ASSERT(inSettings.mNumVelocityStepsOverride < 256);123JPH_ASSERT(inSettings.mNumPositionStepsOverride < 256);124}125126/// Virtual destructor127virtual ~Constraint() = default;128129/// Get the type of a constraint130virtual EConstraintType GetType() const { return EConstraintType::Constraint; }131132/// Get the sub type of a constraint133virtual EConstraintSubType GetSubType() const = 0;134135/// Priority of the constraint when solving. Higher numbers have are more likely to be solved correctly.136/// 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.137uint32 GetConstraintPriority() const { return mConstraintPriority; }138void SetConstraintPriority(uint32 inPriority) { mConstraintPriority = inPriority; }139140/// 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.141void SetNumVelocityStepsOverride(uint inN) { JPH_ASSERT(inN < 256); mNumVelocityStepsOverride = uint8(inN); }142uint GetNumVelocityStepsOverride() const { return mNumVelocityStepsOverride; }143144/// 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.145void SetNumPositionStepsOverride(uint inN) { JPH_ASSERT(inN < 256); mNumPositionStepsOverride = uint8(inN); }146uint GetNumPositionStepsOverride() const { return mNumPositionStepsOverride; }147148/// Enable / disable this constraint. This can e.g. be used to implement a breakable constraint by detecting that the constraint impulse149/// (see e.g. PointConstraint::GetTotalLambdaPosition) went over a certain limit and then disabling the constraint.150/// Note that although a disabled constraint will not affect the simulation in any way anymore, it does incur some processing overhead.151/// 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).152void SetEnabled(bool inEnabled) { mEnabled = inEnabled; }153154/// Test if a constraint is enabled.155bool GetEnabled() const { return mEnabled; }156157/// Access to the user data, can be used for anything by the application158uint64 GetUserData() const { return mUserData; }159void SetUserData(uint64 inUserData) { mUserData = inUserData; }160161/// Notify the constraint that the shape of a body has changed and that its center of mass has moved by inDeltaCOM.162/// Bodies don't know which constraints are connected to them so the user is responsible for notifying the relevant constraints when a body changes.163/// @param inBodyID ID of the body that has changed164/// @param inDeltaCOM The delta of the center of mass of the body (shape->GetCenterOfMass() - shape_before_change->GetCenterOfMass())165virtual void NotifyShapeChanged(const BodyID &inBodyID, Vec3Arg inDeltaCOM) = 0;166167/// 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.168/// 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 that169/// 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 changes170/// 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).171virtual void ResetWarmStart() = 0;172173///@name Solver interface174///@{175virtual bool IsActive() const { return mEnabled; }176virtual void SetupVelocityConstraint(float inDeltaTime) = 0;177virtual void WarmStartVelocityConstraint(float inWarmStartImpulseRatio) = 0;178virtual bool SolveVelocityConstraint(float inDeltaTime) = 0;179virtual bool SolvePositionConstraint(float inDeltaTime, float inBaumgarte) = 0;180///@}181182/// Link bodies that are connected by this constraint in the island builder183virtual void BuildIslands(uint32 inConstraintIndex, IslandBuilder &ioBuilder, BodyManager &inBodyManager) = 0;184185/// Link bodies that are connected by this constraint in the same split. Returns the split index.186virtual uint BuildIslandSplits(LargeIslandSplitter &ioSplitter) const = 0;187188#ifdef JPH_DEBUG_RENDERER189// Drawing interface190virtual void DrawConstraint(DebugRenderer *inRenderer) const = 0;191virtual void DrawConstraintLimits([[maybe_unused]] DebugRenderer *inRenderer) const { }192virtual void DrawConstraintReferenceFrame([[maybe_unused]] DebugRenderer *inRenderer) const { }193194/// Size of constraint when drawing it through the debug renderer195float GetDrawConstraintSize() const { return mDrawConstraintSize; }196void SetDrawConstraintSize(float inSize) { mDrawConstraintSize = inSize; }197#endif // JPH_DEBUG_RENDERER198199/// Saving state for replay200virtual void SaveState(StateRecorder &inStream) const;201202/// Restoring state for replay203virtual void RestoreState(StateRecorder &inStream);204205/// Debug function to convert a constraint to its settings, note that this will not save to which bodies the constraint is connected to206virtual Ref<ConstraintSettings> GetConstraintSettings() const = 0;207208protected:209/// Helper function to copy settings back to constraint settings for this base class210void ToConstraintSettings(ConstraintSettings &outSettings) const;211212#ifdef JPH_DEBUG_RENDERER213/// Size of constraint when drawing it through the debug renderer214float mDrawConstraintSize;215#endif // JPH_DEBUG_RENDERER216217private:218friend class ConstraintManager;219220/// Index that indicates this constraint is not in the constraint manager221static constexpr uint32 cInvalidConstraintIndex = 0xffffffff;222223/// Index in the mConstraints list of the ConstraintManager for easy finding224uint32 mConstraintIndex = cInvalidConstraintIndex;225226/// Priority of the constraint when solving. Higher numbers have are more likely to be solved correctly.227uint32 mConstraintPriority = 0;228229/// 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.230uint8 mNumVelocityStepsOverride = 0;231232/// 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.233uint8 mNumPositionStepsOverride = 0;234235/// If this constraint is currently enabled236bool mEnabled = true;237238/// User data value (can be used by application)239uint64 mUserData;240};241242JPH_NAMESPACE_END243244245