CharacterVirtual.h 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  2. // SPDX-License-Identifier: MIT
  3. #pragma once
  4. #include <Jolt/Physics/Character/CharacterBase.h>
  5. #include <Jolt/Physics/Body/MotionType.h>
  6. #include <Jolt/Physics/Body/BodyFilter.h>
  7. #include <Jolt/Physics/Collision/BroadPhase/BroadPhaseLayer.h>
  8. #include <Jolt/Physics/Collision/ObjectLayer.h>
  9. #include <Jolt/Core/STLTempAllocator.h>
  10. JPH_NAMESPACE_BEGIN
  11. class CharacterVirtual;
  12. /// Contains the configuration of a character
  13. class CharacterVirtualSettings : public CharacterBaseSettings
  14. {
  15. public:
  16. JPH_OVERRIDE_NEW_DELETE
  17. /// Character mass (kg). Used to push down objects with gravity when the character is standing on top.
  18. float mMass = 70.0f;
  19. /// Maximum force with which the character can push other bodies (N).
  20. float mMaxStrength = 100.0f;
  21. ///@name Movement settings
  22. float mPredictiveContactDistance = 0.1f; ///< How far to scan outside of the shape for predictive contacts
  23. uint mMaxCollisionIterations = 5; ///< Max amount of collision loops
  24. uint mMaxConstraintIterations = 15; ///< How often to try stepping in the constraint solving
  25. float mMinTimeRemaining = 1.0e-4f; ///< Early out condition: If this much time is left to simulate we are done
  26. float mCollisionTolerance = 1.0e-3f; ///< How far we're willing to penetrate geometry
  27. float mCharacterPadding = 0.02f; ///< How far we try to stay away from the geometry, this ensures that the sweep will hit as little as possible lowering the collision cost and reducing the risk of getting stuck
  28. uint mMaxNumHits = 256; ///< Max num hits to collect in order to avoid excess of contact points collection
  29. float mPenetrationRecoverySpeed = 1.0f; ///< This value governs how fast a penetration will be resolved, 0 = nothing is resolved, 1 = everything in one update
  30. };
  31. /// This class contains settings that allow you to override the behavior of a character's collision response
  32. class CharacterContactSettings
  33. {
  34. public:
  35. bool mCanPushCharacter = true; ///< True when the object can push the virtual character
  36. bool mCanReceiveImpulses = true; ///< True when the virtual character can apply impulses (push) the body
  37. };
  38. /// This class receives callbacks when a virtual character hits something.
  39. class CharacterContactListener
  40. {
  41. public:
  42. JPH_OVERRIDE_NEW_DELETE
  43. /// Destructor
  44. virtual ~CharacterContactListener() = default;
  45. /// Checks if a character can collide with specified body. Return true if the contact is valid.
  46. virtual bool OnContactValidate(const CharacterVirtual *inCharacter, const BodyID &inBodyID2, const SubShapeID &inSubShapeID2) { return true; }
  47. /// Called whenever the character collides with a body. Returns true if the contact can push the character.
  48. virtual void OnContactAdded(const CharacterVirtual *inCharacter, const BodyID &inBodyID2, const SubShapeID &inSubShapeID2, Vec3Arg inContactPosition, Vec3Arg inContactNormal, CharacterContactSettings &ioSettings) { /* Default do nothing */ }
  49. /// Called whenever a contact is being used by the solver. Allows the listener to override the resulting character velocity (e.g. by preventing sliding along certain surfaces).
  50. /// @param inCharacter Character that is being solved
  51. /// @param inBodyID2 Body ID of body that is being hit
  52. /// @param inSubShapeID2 Sub shape ID of shape that is being hit
  53. /// @param inContactPosition World space contact position
  54. /// @param inContactNormal World space contact normal
  55. /// @param inContactVelocity World space velocity of contact point (e.g. for a moving platform)
  56. /// @param inContactMaterial Material of contact point
  57. /// @param inCharacterVelocity World space velocity of the character prior to hitting this contact
  58. /// @param ioNewCharacterVelocity Contains the calculated world space velocity of the character after hitting this contact, this velocity slides along the surface of the contact. Can be modified by the listener to provide an alternative velocity.
  59. virtual void OnContactSolve(const CharacterVirtual *inCharacter, const BodyID &inBodyID2, const SubShapeID &inSubShapeID2, Vec3Arg inContactPosition, Vec3Arg inContactNormal, Vec3Arg inContactVelocity, const PhysicsMaterial *inContactMaterial, Vec3Arg inCharacterVelocity, Vec3 &ioNewCharacterVelocity) { /* Default do nothing */ }
  60. };
  61. /// Runtime character object.
  62. /// This object usually represents the player. Contrary to the Character class it doesn't use a rigid body but moves doing collision checks only (hence the name virtual).
  63. /// The advantage of this is that you can determine when the character moves in the frame (usually this has to happen at a very particular point in the frame)
  64. /// but the downside is that other objects don't see this virtual character. In order to make this work it is recommended to pair a CharacterVirtual with a Character that
  65. /// moves along. This Character should be keyframed (or at least have no gravity) and move along with the CharacterVirtual so that other rigid bodies can collide with it.
  66. class CharacterVirtual : public CharacterBase
  67. {
  68. public:
  69. JPH_OVERRIDE_NEW_DELETE
  70. /// Constructor
  71. /// @param inSettings The settings for the character
  72. /// @param inPosition Initial position for the character
  73. /// @param inRotation Initial rotation for the character (usually only around the up-axis)
  74. /// @param inSystem Physics system that this character will be added to later
  75. CharacterVirtual(const CharacterVirtualSettings *inSettings, Vec3Arg inPosition, QuatArg inRotation, PhysicsSystem *inSystem);
  76. /// Set the contact listener
  77. void SetListener(CharacterContactListener *inListener) { mListener = inListener; }
  78. /// Get the current contact listener
  79. CharacterContactListener * GetListener() const { return mListener; }
  80. /// Get the linear velocity of the character (m / s)
  81. Vec3 GetLinearVelocity() const { return mLinearVelocity; }
  82. /// Set the linear velocity of the character (m / s)
  83. void SetLinearVelocity(Vec3Arg inLinearVelocity) { mLinearVelocity = inLinearVelocity; }
  84. /// Get the position of the character
  85. Vec3 GetPosition() const { return mPosition; }
  86. /// Set the position of the character
  87. void SetPosition(Vec3Arg inPosition) { mPosition = inPosition; }
  88. /// Get the rotation of the character
  89. Quat GetRotation() const { return mRotation; }
  90. /// Set the rotation of the character
  91. void SetRotation(QuatArg inRotation) { mRotation = inRotation; }
  92. /// Calculate the world transform of the character
  93. Mat44 GetWorldTransform() const { return Mat44::sRotationTranslation(mRotation, mPosition); }
  94. /// Calculates the transform for this character's center of mass
  95. Mat44 GetCenterOfMassTransform() const { return GetCenterOfMassTransform(mPosition, mRotation, mShape); }
  96. /// Character mass (kg)
  97. void SetMass(float inMass) { mMass = inMass; }
  98. /// Maximum force with which the character can push other bodies (N)
  99. void SetMaxStrength(float inMaxStrength) { mMaxStrength = inMaxStrength; }
  100. /// Character padding
  101. float GetCharacterPadding() const { return mCharacterPadding; }
  102. /// This function can be called prior to calling Update() to convert a desired velocity into a velocity that won't make the character move further onto steep slopes.
  103. /// This velocity can then be set on the character using SetLinearVelocity()
  104. /// @param inDesiredVelocity Velocity to clamp against steep walls
  105. /// @return A new velocity vector that won't make the character move up steep slopes
  106. Vec3 CancelVelocityTowardsSteepSlopes(Vec3Arg inDesiredVelocity) const;
  107. /// This is the main update function. It moves the character according to its current velocity (the character is similar to a kinematic body in the sense
  108. /// that you set the velocity and the character will follow unless collision is blocking the way). Note it's your own responsibility to apply gravity to the character velocity!
  109. /// Different surface materials (like ice) can be emulated by getting the ground material and adjusting the velocity and/or the max slope angle accordingly every frame.
  110. /// @param inDeltaTime Time step to simulate.
  111. /// @param inGravity Gravity vector (m/s^2). This gravity vector is only used when the character is standing on top of another object to apply downward force.
  112. /// @param inBroadPhaseLayerFilter Filter that is used to check if the character collides with something in the broadphase.
  113. /// @param inObjectLayerFilter Filter that is used to check if a character collides with a layer.
  114. /// @param inBodyFilter Filter that is used to check if a character collides with a body.
  115. /// @param inAllocator An allocator for temporary allocations. All memory will be freed by the time this function returns.
  116. void Update(float inDeltaTime, Vec3Arg inGravity, const BroadPhaseLayerFilter &inBroadPhaseLayerFilter, const ObjectLayerFilter &inObjectLayerFilter, const BodyFilter &inBodyFilter, TempAllocator &inAllocator);
  117. /// This function will return true if the character has moved into a slope that is too steep (e.g. a vertical wall).
  118. /// You would call WalkStairs to attempt to step up stairs.
  119. /// @param inLinearVelocity The linear velocity that the player desired. This is used to determine if we're pusing into a step.
  120. bool CanWalkStairs(Vec3Arg inLinearVelocity) const;
  121. /// When stair walking is needed, you can call the WalkStairs function to cast up, forward and down again to try to find a valid position
  122. /// @param inDeltaTime Time step to simulate.
  123. /// @param inStepUp The direction and distance to step up (this corresponds to the max step height)
  124. /// @param inStepForward The direction and distance to step forward after the step up
  125. /// @param inStepForwardTest When running at a high frequency, inStepForward can be very small and it's likely that you hit the side of the stairs on the way down. This could produce a normal that violates the max slope angle. If this happens, we test again using this distance from the up position to see if we find a valid slope.
  126. /// @param inStepDownExtra An additional translation that is added when stepping down at the end. Allows you to step further down than up. Set to zero if you don't want this. Should be in the opposite direction of up.
  127. /// @param inBroadPhaseLayerFilter Filter that is used to check if the character collides with something in the broadphase.
  128. /// @param inObjectLayerFilter Filter that is used to check if a character collides with a layer.
  129. /// @param inBodyFilter Filter that is used to check if a character collides with a body.
  130. /// @param inAllocator An allocator for temporary allocations. All memory will be freed by the time this function returns.
  131. /// @return true if the stair walk was successful
  132. bool WalkStairs(float inDeltaTime, Vec3Arg inStepUp, Vec3Arg inStepForward, Vec3Arg inStepForwardTest, Vec3Arg inStepDownExtra, const BroadPhaseLayerFilter &inBroadPhaseLayerFilter, const ObjectLayerFilter &inObjectLayerFilter, const BodyFilter &inBodyFilter, TempAllocator &inAllocator);
  133. /// This function can be used to artificially keep the character to the floor. Normally when a character is on a small step and starts moving horizontally, the character will
  134. /// lose contact with the floor because the initial vertical velocity is zero while the horizontal velocity is quite high. To prevent the character from losing contact with the floor,
  135. /// we do an additional collision check downwards and if we find the floor within a certain distance, we project the character onto the floor.
  136. /// @param inStepDown Max amount to project the character downwards (if no floor is found within this distance, the function will return false)
  137. /// @param inBroadPhaseLayerFilter Filter that is used to check if the character collides with something in the broadphase.
  138. /// @param inObjectLayerFilter Filter that is used to check if a character collides with a layer.
  139. /// @param inBodyFilter Filter that is used to check if a character collides with a body.
  140. /// @param inAllocator An allocator for temporary allocations. All memory will be freed by the time this function returns.
  141. /// @return True if the character was successfully projected onto the floor.
  142. bool StickToFloor(Vec3Arg inStepDown, const BroadPhaseLayerFilter &inBroadPhaseLayerFilter, const ObjectLayerFilter &inObjectLayerFilter, const BodyFilter &inBodyFilter, TempAllocator &inAllocator);
  143. /// Settings struct with settings for ExtendedUpdate
  144. struct ExtendedUpdateSettings
  145. {
  146. Vec3Arg mStickToFloorStepDown { 0, -0.5f, 0 }; ///< See StickToFloor inStepDown parameter. Can be zero to turn off.
  147. Vec3Arg mWalkStairsStepUp { 0, 0.4f, 0 }; ///< See WalkStairs inStepUp parameter. Can be zero to turn off.
  148. float mWalkStairsMinStepForward { 0.02f }; ///< See WalkStairs inStepForward parameter. Note that the parameter only indicates a magnitude, direction is taken from current velocity.
  149. float mWalkStairsStepForwardTest { 0.15f }; ///< See WalkStairs inStepForwardTest parameter. Note that the parameter only indicates a magnitude, direction is taken from current velocity.
  150. float mWalkStairsCosAngleForwardContact { Cos(DegreesToRadians(75.0f)) }; ///< Cos(angle) where angle is the maximum angle between the ground normal in the horizontal plane and the character forward vector where we're willing to adjust the step forward test towards the contact normal.
  151. Vec3Arg mWalkStairsStepDownExtra { Vec3::sZero() }; ///< See WalkStairs inStepDownExtra
  152. };
  153. /// This function combines Update, StickToFloor and WalkStairs. This function serves as an example of how these functions could be combined.
  154. /// Before calling, call SetLinearVelocity to update the horizontal/vertical speed of the character, typically this is:
  155. /// - When on OnGround and not moving away from ground: velocity = GetGroundVelocity() + horizontal speed as input by player + optional vertical jump velocity + delta time * gravity
  156. /// - Else: velocity = current vertical velocity + horizontal speed as input by player + delta time * gravity
  157. /// @param inDeltaTime Time step to simulate.
  158. /// @param inGravity Gravity vector (m/s^2). This gravity vector is only used when the character is standing on top of another object to apply downward force.
  159. /// @param inSettings A structure containing settings for the algorithm.
  160. /// @param inBroadPhaseLayerFilter Filter that is used to check if the character collides with something in the broadphase.
  161. /// @param inObjectLayerFilter Filter that is used to check if a character collides with a layer.
  162. /// @param inBodyFilter Filter that is used to check if a character collides with a body.
  163. /// @param inAllocator An allocator for temporary allocations. All memory will be freed by the time this function returns.
  164. void ExtendedUpdate(float inDeltaTime, Vec3Arg inGravity, const ExtendedUpdateSettings &inSettings, const BroadPhaseLayerFilter &inBroadPhaseLayerFilter, const ObjectLayerFilter &inObjectLayerFilter, const BodyFilter &inBodyFilter, TempAllocator &inAllocator);
  165. /// This function can be used after a character has teleported to determine the new contacts with the world.
  166. void RefreshContacts(const BroadPhaseLayerFilter &inBroadPhaseLayerFilter, const ObjectLayerFilter &inObjectLayerFilter, const BodyFilter &inBodyFilter, TempAllocator &inAllocator);
  167. /// Switch the shape of the character (e.g. for stance).
  168. /// @param inShape The shape to switch to.
  169. /// @param inMaxPenetrationDepth When inMaxPenetrationDepth is not FLT_MAX, it checks if the new shape collides before switching shape. This is the max penetration we're willing to accept after the switch.
  170. /// @param inBroadPhaseLayerFilter Filter that is used to check if the character collides with something in the broadphase.
  171. /// @param inObjectLayerFilter Filter that is used to check if a character collides with a layer.
  172. /// @param inBodyFilter Filter that is used to check if a character collides with a body.
  173. /// @param inAllocator An allocator for temporary allocations. All memory will be freed by the time this function returns.
  174. /// @return Returns true if the switch succeeded.
  175. bool SetShape(const Shape *inShape, float inMaxPenetrationDepth, const BroadPhaseLayerFilter &inBroadPhaseLayerFilter, const ObjectLayerFilter &inObjectLayerFilter, const BodyFilter &inBodyFilter, TempAllocator &inAllocator);
  176. /// @brief Get all contacts for the character at a particular location
  177. /// @param inPosition Position to test, note that this position will be corrected for the character padding.
  178. /// @param inRotation Rotation at which to test the shape.
  179. /// @param inMovementDirection A hint in which direction the character is moving, will be used to calculate a proper normal.
  180. /// @param inMaxSeparationDistance How much distance around the character you want to report contacts in (can be 0 to match the character exactly).
  181. /// @param inShape Shape to test collision with.
  182. /// @param ioCollector Collision collector that receives the collision results.
  183. /// @param inBroadPhaseLayerFilter Filter that is used to check if the character collides with something in the broadphase.
  184. /// @param inObjectLayerFilter Filter that is used to check if a character collides with a layer.
  185. /// @param inBodyFilter Filter that is used to check if a character collides with a body.
  186. void CheckCollision(Vec3Arg inPosition, QuatArg inRotation, Vec3Arg inMovementDirection, float inMaxSeparationDistance, const Shape *inShape, CollideShapeCollector &ioCollector, const BroadPhaseLayerFilter &inBroadPhaseLayerFilter, const ObjectLayerFilter &inObjectLayerFilter, const BodyFilter &inBodyFilter) const;
  187. // Saving / restoring state for replay
  188. virtual void SaveState(StateRecorder &inStream) const override;
  189. virtual void RestoreState(StateRecorder &inStream) override;
  190. #ifdef JPH_DEBUG_RENDERER
  191. static inline bool sDrawConstraints = false; ///< Draw the current state of the constraints for iteration 0 when creating them
  192. static inline bool sDrawWalkStairs = false; ///< Draw the state of the walk stairs algorithm
  193. static inline bool sDrawStickToFloor = false; ///< Draw the state of the stick to floor algorithm
  194. #endif
  195. private:
  196. // Encapsulates a collision contact
  197. struct Contact
  198. {
  199. Vec3 mPosition; ///< Position where the character makes contact
  200. Vec3 mLinearVelocity; ///< Velocity of the contact point
  201. Vec3 mContactNormal; ///< Contact normal, pointing towards the character
  202. Vec3 mSurfaceNormal; ///< Surface normal of the contact
  203. float mDistance; ///< Distance to the contact <= 0 means that it is an actual contact, > 0 means predictive
  204. float mFraction; ///< Fraction along the path where this contact takes place
  205. BodyID mBodyB; ///< ID of body we're colliding with
  206. SubShapeID mSubShapeIDB; ///< Sub shape ID of body we're colliding with
  207. EMotionType mMotionTypeB; ///< Motion type of B, used to determine the priority of the contact
  208. uint64 mUserData; ///< User data of B
  209. const PhysicsMaterial * mMaterial; ///< Material of B
  210. bool mHadCollision = false; ///< If the character actually collided with the contact (can be false if a predictive contact never becomes a real one)
  211. bool mWasDiscarded = false; ///< If the contact validate callback chose to discard this contact
  212. bool mCanPushCharacter = true; ///< When true, the velocity of the contact point can push the character
  213. };
  214. using TempContactList = std::vector<Contact, STLTempAllocator<Contact>>;
  215. using ContactList = Array<Contact>;
  216. // A contact that needs to be ignored
  217. struct IgnoredContact
  218. {
  219. IgnoredContact() = default;
  220. IgnoredContact(const BodyID &inBodyID, const SubShapeID &inSubShapeID) : mBodyID(inBodyID), mSubShapeID(inSubShapeID) { }
  221. BodyID mBodyID; ///< ID of body we're colliding with
  222. SubShapeID mSubShapeID; ///< Sub shape of body we're colliding with
  223. };
  224. using IgnoredContactList = std::vector<IgnoredContact, STLTempAllocator<IgnoredContact>>;
  225. // A constraint that limits the movement of the character
  226. struct Constraint
  227. {
  228. Contact * mContact; ///< Contact that this constraint was generated from
  229. float mTOI; ///< Calculated time of impact (can be negative if penetrating)
  230. float mProjectedVelocity; ///< Velocity of the contact projected on the contact normal (negative if separating)
  231. Vec3 mLinearVelocity; ///< Velocity of the contact (can contain a corrective velocity to resolve penetration)
  232. Plane mPlane; ///< Plane around the origin that describes how far we can displace (from the origin)
  233. };
  234. using ConstraintList = std::vector<Constraint, STLTempAllocator<Constraint>>;
  235. // Collision collector that collects hits for CollideShape
  236. class ContactCollector : public CollideShapeCollector
  237. {
  238. public:
  239. ContactCollector(PhysicsSystem *inSystem, uint inMaxHits, Vec3Arg inUp, TempContactList &outContacts) : mUp(inUp), mSystem(inSystem), mContacts(outContacts), mMaxHits(inMaxHits) { }
  240. virtual void AddHit(const CollideShapeResult &inResult) override;
  241. Vec3 mUp;
  242. PhysicsSystem * mSystem;
  243. TempContactList & mContacts;
  244. uint mMaxHits;
  245. };
  246. // A collision collector that collects hits for CastShape
  247. class ContactCastCollector : public CastShapeCollector
  248. {
  249. public:
  250. ContactCastCollector(PhysicsSystem *inSystem, Vec3Arg inDisplacement, uint inMaxHits, Vec3Arg inUp, const IgnoredContactList &inIgnoredContacts, TempContactList &outContacts) : mDisplacement(inDisplacement), mUp(inUp), mSystem(inSystem), mIgnoredContacts(inIgnoredContacts), mContacts(outContacts), mMaxHits(inMaxHits) { }
  251. virtual void AddHit(const ShapeCastResult &inResult) override;
  252. Vec3 mDisplacement;
  253. Vec3 mUp;
  254. PhysicsSystem * mSystem;
  255. const IgnoredContactList & mIgnoredContacts;
  256. TempContactList & mContacts;
  257. uint mMaxHits;
  258. };
  259. // Helper function to convert a Jolt collision result into a contact
  260. template <class taCollector>
  261. inline static void sFillContactProperties(Contact &outContact, const Body &inBody, Vec3Arg inUp, const taCollector &inCollector, const CollideShapeResult &inResult);
  262. // Move the shape from ioPosition and try to displace it by inVelocity * inDeltaTime, this will try to slide the shape along the world geometry
  263. void MoveShape(Vec3 &ioPosition, Vec3Arg inVelocity, float inDeltaTime, ContactList *outActiveContacts, const BroadPhaseLayerFilter &inBroadPhaseLayerFilter, const ObjectLayerFilter &inObjectLayerFilter, const BodyFilter &inBodyFilter, TempAllocator &inAllocator
  264. #ifdef JPH_DEBUG_RENDERER
  265. , bool inDrawConstraints = false
  266. #endif // JPH_DEBUG_RENDERER
  267. ) const;
  268. // Ask the callback if inContact is a valid contact point
  269. bool ValidateContact(const Contact &inContact) const;
  270. // Tests the shape for collision around inPosition
  271. void GetContactsAtPosition(Vec3Arg inPosition, Vec3Arg inMovementDirection, const Shape *inShape, TempContactList &outContacts, const BroadPhaseLayerFilter &inBroadPhaseLayerFilter, const ObjectLayerFilter &inObjectLayerFilter, const BodyFilter &inBodyFilter) const;
  272. // Remove penetrating contacts with the same body that have conflicting normals, leaving these will make the character mover get stuck
  273. void RemoveConflictingContacts(TempContactList &ioContacts, IgnoredContactList &outIgnoredContacts) const;
  274. // Convert contacts into constraints. The character is assumed to start at the origin and the constraints are planes around the origin that confine the movement of the character.
  275. void DetermineConstraints(TempContactList &inContacts, ConstraintList &outConstraints) const;
  276. // Use the constraints to solve the displacement of the character. This will slide the character on the planes around the origin for as far as possible.
  277. void SolveConstraints(Vec3Arg inVelocity, float inDeltaTime, float inTimeRemaining, ConstraintList &ioConstraints, IgnoredContactList &ioIgnoredContacts, float &outTimeSimulated, Vec3 &outDisplacement, TempAllocator &inAllocator
  278. #ifdef JPH_DEBUG_RENDERER
  279. , bool inDrawConstraints = false
  280. #endif // JPH_DEBUG_RENDERER
  281. ) const;
  282. // Handle contact with physics object that we're colliding against
  283. bool HandleContact(Vec3Arg inVelocity, Constraint &ioConstraint, float inDeltaTime) const;
  284. // Does a swept test of the shape from inPosition with displacement inDisplacement, returns true if there was a collision
  285. bool GetFirstContactForSweep(Vec3Arg inPosition, Vec3Arg inDisplacement, Contact &outContact, const IgnoredContactList &inIgnoredContacts, const BroadPhaseLayerFilter &inBroadPhaseLayerFilter, const ObjectLayerFilter &inObjectLayerFilter, const BodyFilter &inBodyFilter, TempAllocator &inAllocator) const;
  286. // Store contacts so that we have proper ground information
  287. void StoreActiveContacts(const TempContactList &inContacts, TempAllocator &inAllocator);
  288. // This function will determine which contacts are touching the character and will calculate the one that is supporting us
  289. void UpdateSupportingContact(bool inSkipContactVelocityCheck, TempAllocator &inAllocator);
  290. /// This function can be called after moving the character to a new colliding position
  291. void MoveToContact(Vec3Arg inPosition, const Contact &inContact, const BroadPhaseLayerFilter &inBroadPhaseLayerFilter, const ObjectLayerFilter &inObjectLayerFilter, const BodyFilter &inBodyFilter, TempAllocator &inAllocator);
  292. // This function returns the actual center of mass of the shape, not corrected for the character padding
  293. inline Mat44 GetCenterOfMassTransform(Vec3Arg inPosition, QuatArg inRotation, const Shape *inShape) const
  294. {
  295. return Mat44::sRotationTranslation(inRotation, inPosition).PreTranslated(inShape->GetCenterOfMass()).PostTranslated(mCharacterPadding * mUp);
  296. }
  297. // Our main listener for contacts
  298. CharacterContactListener * mListener = nullptr;
  299. // Movement settings
  300. float mPredictiveContactDistance; // How far to scan outside of the shape for predictive contacts
  301. uint mMaxCollisionIterations; // Max amount of collision loops
  302. uint mMaxConstraintIterations; // How often to try stepping in the constraint solving
  303. float mMinTimeRemaining; // Early out condition: If this much time is left to simulate we are done
  304. float mCollisionTolerance; // How far we're willing to penetrate geometry
  305. float mCharacterPadding; // How far we try to stay away from the geometry, this ensures that the sweep will hit as little as possible lowering the collision cost and reducing the risk of getting stuck
  306. uint mMaxNumHits; // Max num hits to collect in order to avoid excess of contact points collection
  307. float mPenetrationRecoverySpeed; // This value governs how fast a penetration will be resolved, 0 = nothing is resolved, 1 = everything in one update
  308. // Character mass (kg)
  309. float mMass;
  310. // Maximum force with which the character can push other bodies (N)
  311. float mMaxStrength;
  312. // Current position (of the base, not the center of mass)
  313. Vec3 mPosition = Vec3::sZero();
  314. // Current rotation (of the base, not of the center of mass)
  315. Quat mRotation = Quat::sIdentity();
  316. // Current linear velocity
  317. Vec3 mLinearVelocity = Vec3::sZero();
  318. // List of contacts that were active in the last frame
  319. ContactList mActiveContacts;
  320. // Remembers the delta time of the last update
  321. float mLastDeltaTime = 1.0f / 60.0f;
  322. };
  323. JPH_NAMESPACE_END