Jolt Physics
A multi core friendly Game Physics Engine
Loading...
Searching...
No Matches
CharacterVirtual.h
Go to the documentation of this file.
1// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
2// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
3// SPDX-License-Identifier: MIT
4
5#pragma once
6
13
15
17
20{
21public:
23
25 float mMass = 70.0f;
26
28 float mMaxStrength = 100.0f;
29
31 Vec3 mShapeOffset = Vec3::sZero();
32
35 float mPredictiveContactDistance = 0.1f;
36 uint mMaxCollisionIterations = 5;
37 uint mMaxConstraintIterations = 15;
38 float mMinTimeRemaining = 1.0e-4f;
39 float mCollisionTolerance = 1.0e-3f;
40 float mCharacterPadding = 0.02f;
41 uint mMaxNumHits = 256;
42 float mHitReductionCosMaxAngle = 0.999f;
43 float mPenetrationRecoverySpeed = 1.0f;
44};
45
48{
49public:
50 bool mCanPushCharacter = true;
51 bool mCanReceiveImpulses = true;
52};
53
89
96{
97public:
99
107
110
113
115 CharacterContactListener * GetListener() const { return mListener; }
116
118 Vec3 GetLinearVelocity() const { return mLinearVelocity; }
119
122
124 RVec3 GetPosition() const { return mPosition; }
125
128
130 Quat GetRotation() const { return mRotation; }
131
134
136 RMat44 GetWorldTransform() const { return RMat44::sRotationTranslation(mRotation, mPosition); }
137
139 RMat44 GetCenterOfMassTransform() const { return GetCenterOfMassTransform(mPosition, mRotation, mShape); }
140
142 float GetMass() const { return mMass; }
143 void SetMass(float inMass) { mMass = inMass; }
144
146 float GetMaxStrength() const { return mMaxStrength; }
147 void SetMaxStrength(float inMaxStrength) { mMaxStrength = inMaxStrength; }
148
150 float GetPenetrationRecoverySpeed() const { return mPenetrationRecoverySpeed; }
151 void SetPenetrationRecoverySpeed(float inSpeed) { mPenetrationRecoverySpeed = inSpeed; }
152
154 float GetCharacterPadding() const { return mCharacterPadding; }
155
157 uint GetMaxNumHits() const { return mMaxNumHits; }
158 void SetMaxNumHits(uint inMaxHits) { mMaxNumHits = inMaxHits; }
159
161 float GetHitReductionCosMaxAngle() const { return mHitReductionCosMaxAngle; }
162 void SetHitReductionCosMaxAngle(float inCosMaxAngle) { mHitReductionCosMaxAngle = inCosMaxAngle; }
163
168 bool GetMaxHitsExceeded() const { return mMaxHitsExceeded; }
169
171 Vec3 GetShapeOffset() const { return mShapeOffset; }
173
175 uint64 GetUserData() const { return mUserData; }
177
182 Vec3 CancelVelocityTowardsSteepSlopes(Vec3Arg inDesiredVelocity) const;
183
195
199 bool CanWalkStairs(Vec3Arg inLinearVelocity) const;
200
214
226
229 {
230 Vec3 mStickToFloorStepDown { 0, -0.5f, 0 };
231 Vec3 mWalkStairsStepUp { 0, 0.4f, 0 };
232 float mWalkStairsMinStepForward { 0.02f };
233 float mWalkStairsStepForwardTest { 0.15f };
234 float mWalkStairsCosAngleForwardContact { Cos(DegreesToRadians(75.0f)) };
235 Vec3 mWalkStairsStepDownExtra { Vec3::sZero() };
236 };
237
251
254
257 void UpdateGroundVelocity();
258
269
283
284 // Saving / restoring state for replay
285 virtual void SaveState(StateRecorder &inStream) const override;
286 virtual void RestoreState(StateRecorder &inStream) override;
287
288#ifdef JPH_DEBUG_RENDERER
289 static inline bool sDrawConstraints = false;
290 static inline bool sDrawWalkStairs = false;
291 static inline bool sDrawStickToFloor = false;
292#endif
293
294 // Encapsulates a collision contact
295 struct Contact
296 {
297 // Saving / restoring state for replay
298 void SaveState(StateRecorder &inStream) const;
299 void RestoreState(StateRecorder &inStream);
300
305 float mDistance;
306 float mFraction;
313 bool mHadCollision = false;
314 bool mWasDiscarded = false;
315 bool mCanPushCharacter = true;
316 };
317
318 using TempContactList = std::vector<Contact, STLTempAllocator<Contact>>;
320
322 const ContactList & GetActiveContacts() const { return mActiveContacts; }
323
324private:
325 // Sorting predicate for making contact order deterministic
326 struct ContactOrderingPredicate
327 {
328 inline bool operator () (const Contact &inLHS, const Contact &inRHS) const
329 {
330 if (inLHS.mBodyB != inRHS.mBodyB)
331 return inLHS.mBodyB < inRHS.mBodyB;
332
333 return inLHS.mSubShapeIDB.GetValue() < inRHS.mSubShapeIDB.GetValue();
334 }
335 };
336
337 // A contact that needs to be ignored
338 struct IgnoredContact
339 {
340 IgnoredContact() = default;
341 IgnoredContact(const BodyID &inBodyID, const SubShapeID &inSubShapeID) : mBodyID(inBodyID), mSubShapeID(inSubShapeID) { }
342
343 BodyID mBodyID;
344 SubShapeID mSubShapeID;
345 };
346
347 using IgnoredContactList = std::vector<IgnoredContact, STLTempAllocator<IgnoredContact>>;
348
349 // A constraint that limits the movement of the character
350 struct Constraint
351 {
352 Contact * mContact;
353 float mTOI;
354 float mProjectedVelocity;
355 Vec3 mLinearVelocity;
356 Plane mPlane;
357 bool mIsSteepSlope = false;
358 };
359
360 using ConstraintList = std::vector<Constraint, STLTempAllocator<Constraint>>;
361
362 // Collision collector that collects hits for CollideShape
363 class ContactCollector : public CollideShapeCollector
364 {
365 public:
366 ContactCollector(PhysicsSystem *inSystem, const CharacterVirtual *inCharacter, uint inMaxHits, float inHitReductionCosMaxAngle, Vec3Arg inUp, RVec3Arg inBaseOffset, TempContactList &outContacts) : mBaseOffset(inBaseOffset), mUp(inUp), mSystem(inSystem), mCharacter(inCharacter), mContacts(outContacts), mMaxHits(inMaxHits), mHitReductionCosMaxAngle(inHitReductionCosMaxAngle) { }
367
368 virtual void AddHit(const CollideShapeResult &inResult) override;
369
370 RVec3 mBaseOffset;
371 Vec3 mUp;
372 PhysicsSystem * mSystem;
373 const CharacterVirtual * mCharacter;
374 TempContactList & mContacts;
375 uint mMaxHits;
376 float mHitReductionCosMaxAngle;
377 bool mMaxHitsExceeded = false;
378 };
379
380 // A collision collector that collects hits for CastShape
381 class ContactCastCollector : public CastShapeCollector
382 {
383 public:
384 ContactCastCollector(PhysicsSystem *inSystem, const CharacterVirtual *inCharacter, Vec3Arg inDisplacement, Vec3Arg inUp, const IgnoredContactList &inIgnoredContacts, RVec3Arg inBaseOffset, Contact &outContact) : mBaseOffset(inBaseOffset), mDisplacement(inDisplacement), mUp(inUp), mSystem(inSystem), mCharacter(inCharacter), mIgnoredContacts(inIgnoredContacts), mContact(outContact) { }
385
386 virtual void AddHit(const ShapeCastResult &inResult) override;
387
388 RVec3 mBaseOffset;
389 Vec3 mDisplacement;
390 Vec3 mUp;
391 PhysicsSystem * mSystem;
392 const CharacterVirtual * mCharacter;
393 const IgnoredContactList & mIgnoredContacts;
394 Contact & mContact;
395 };
396
397 // Helper function to convert a Jolt collision result into a contact
398 template <class taCollector>
399 inline static void sFillContactProperties(const CharacterVirtual *inCharacter, Contact &outContact, const Body &inBody, Vec3Arg inUp, RVec3Arg inBaseOffset, const taCollector &inCollector, const CollideShapeResult &inResult);
400
401 // Move the shape from ioPosition and try to displace it by inVelocity * inDeltaTime, this will try to slide the shape along the world geometry
404 , bool inDrawConstraints = false
405 #endif // JPH_DEBUG_RENDERER
406 ) const;
407
408 // Ask the callback if inContact is a valid contact point
409 bool ValidateContact(const Contact &inContact) const;
410
411 // Tests the shape for collision around inPosition
413
414 // Remove penetrating contacts with the same body that have conflicting normals, leaving these will make the character mover get stuck
415 void RemoveConflictingContacts(TempContactList &ioContacts, IgnoredContactList &outIgnoredContacts) const;
416
417 // 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.
418 void DetermineConstraints(TempContactList &inContacts, float inDeltaTime, ConstraintList &outConstraints) const;
419
420 // 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.
421 void SolveConstraints(Vec3Arg inVelocity, float inDeltaTime, float inTimeRemaining, ConstraintList &ioConstraints, IgnoredContactList &ioIgnoredContacts, float &outTimeSimulated, Vec3 &outDisplacement, TempAllocator &inAllocator
423 , bool inDrawConstraints = false
424 #endif // JPH_DEBUG_RENDERER
425 ) const;
426
427 // Get the velocity of a body adjusted by the contact listener
428 void GetAdjustedBodyVelocity(const Body& inBody, Vec3 &outLinearVelocity, Vec3 &outAngularVelocity) const;
429
430 // Calculate the ground velocity of the character assuming it's standing on an object with specified linear and angular velocity and with specified center of mass.
431 // Note that we don't just take the point velocity because a point on an object with angular velocity traces an arc,
432 // so if you just take point velocity * delta time you get an error that accumulates over time
433 Vec3 CalculateCharacterGroundVelocity(RVec3Arg inCenterOfMass, Vec3Arg inLinearVelocity, Vec3Arg inAngularVelocity, float inDeltaTime) const;
434
435 // Handle contact with physics object that we're colliding against
436 bool HandleContact(Vec3Arg inVelocity, Constraint &ioConstraint, float inDeltaTime) const;
437
438 // Does a swept test of the shape from inPosition with displacement inDisplacement, returns true if there was a collision
440
441 // Store contacts so that we have proper ground information
442 void StoreActiveContacts(const TempContactList &inContacts, TempAllocator &inAllocator);
443
444 // This function will determine which contacts are touching the character and will calculate the one that is supporting us
445 void UpdateSupportingContact(bool inSkipContactVelocityCheck, TempAllocator &inAllocator);
446
449
450 // This function returns the actual center of mass of the shape, not corrected for the character padding
451 inline RMat44 GetCenterOfMassTransform(RVec3Arg inPosition, QuatArg inRotation, const Shape *inShape) const
452 {
453 return RMat44::sRotationTranslation(inRotation, inPosition).PreTranslated(mShapeOffset + inShape->GetCenterOfMass()).PostTranslated(mCharacterPadding * mUp);
454 }
455
456 // Our main listener for contacts
457 CharacterContactListener * mListener = nullptr;
458
459 // Movement settings
460 EBackFaceMode mBackFaceMode; // When colliding with back faces, the character will not be able to move through back facing triangles. Use this if you have triangles that need to collide on both sides.
461 float mPredictiveContactDistance; // How far to scan outside of the shape for predictive contacts. A value of 0 will most likely cause the character to get stuck as it cannot properly calculate a sliding direction anymore. A value that's too high will cause ghost collisions.
462 uint mMaxCollisionIterations; // Max amount of collision loops
463 uint mMaxConstraintIterations; // How often to try stepping in the constraint solving
464 float mMinTimeRemaining; // Early out condition: If this much time is left to simulate we are done
465 float mCollisionTolerance; // How far we're willing to penetrate geometry
466 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
467 uint mMaxNumHits; // Max num hits to collect in order to avoid excess of contact points collection
468 float mHitReductionCosMaxAngle; // Cos(angle) where angle is the maximum angle between two hits contact normals that are allowed to be merged during hit reduction. Default is around 2.5 degrees. Set to -1 to turn off.
469 float mPenetrationRecoverySpeed; // This value governs how fast a penetration will be resolved, 0 = nothing is resolved, 1 = everything in one update
470
471 // Character mass (kg)
472 float mMass;
473
474 // Maximum force with which the character can push other bodies (N)
475 float mMaxStrength;
476
477 // An extra offset applied to the shape in local space. This allows applying an extra offset to the shape in local space.
478 Vec3 mShapeOffset = Vec3::sZero();
479
480 // Current position (of the base, not the center of mass)
481 RVec3 mPosition = RVec3::sZero();
482
483 // Current rotation (of the base, not of the center of mass)
484 Quat mRotation = Quat::sIdentity();
485
486 // Current linear velocity
487 Vec3 mLinearVelocity = Vec3::sZero();
488
489 // List of contacts that were active in the last frame
490 ContactList mActiveContacts;
491
492 // Remembers the delta time of the last update
493 float mLastDeltaTime = 1.0f / 60.0f;
494
495 // Remember if we exceeded the maximum number of hits and had to remove similar contacts
496 mutable bool mMaxHitsExceeded = false;
497
498 // User data, can be used for anything by the application
499 uint64 mUserData = 0;
500};
501
EBackFaceMode
How collision detection functions will treat back facing triangles.
Definition BackFaceMode.h:11
@ CollideWithBackFaces
Collide with back facing surfaces/triangles.
#define JPH_EXPORT
Definition Core.h:227
std::uint64_t uint64
Definition Core.h:443
unsigned int uint
Definition Core.h:439
#define JPH_NAMESPACE_END
Definition Core.h:367
#define JPH_NAMESPACE_BEGIN
Definition Core.h:361
constexpr float DegreesToRadians(float inV)
Convert a value from degrees to radians.
Definition Math.h:13
AllocateFunction Allocate
Definition Memory.cpp:59
#define JPH_OVERRIDE_NEW_DELETE
Macro to override the new and delete functions.
Definition Memory.h:29
EMotionType
Motion type of a physics body.
Definition MotionType.h:11
std::vector< T, STLAllocator< T > > Array
Definition STLAllocator.h:81
JPH_INLINE float Cos(float inX)
Cosine of x (input in radians)
Definition Trigonometry.h:20
Class function to filter out bodies, returns true if test should collide with body.
Definition BodyFilter.h:16
Definition Body.h:35
ID of a body. This is a way of reasoning about bodies in a multithreaded simulation while avoiding ra...
Definition BodyID.h:13
Filter class for broadphase layers.
Definition BroadPhaseLayer.h:94
Base class for character class.
Definition CharacterBase.h:51
Base class for configuration of a character.
Definition CharacterBase.h:21
This class receives callbacks when a virtual character hits something.
Definition CharacterVirtual.h:56
virtual void OnContactAdded(const CharacterVirtual *inCharacter, const BodyID &inBodyID2, const SubShapeID &inSubShapeID2, RVec3Arg inContactPosition, Vec3Arg inContactNormal, CharacterContactSettings &ioSettings)
Definition CharacterVirtual.h:75
virtual ~CharacterContactListener()=default
Destructor.
virtual bool OnContactValidate(const CharacterVirtual *inCharacter, const BodyID &inBodyID2, const SubShapeID &inSubShapeID2)
Checks if a character can collide with specified body. Return true if the contact is valid.
Definition CharacterVirtual.h:66
virtual void OnContactSolve(const CharacterVirtual *inCharacter, const BodyID &inBodyID2, const SubShapeID &inSubShapeID2, RVec3Arg inContactPosition, Vec3Arg inContactNormal, Vec3Arg inContactVelocity, const PhysicsMaterial *inContactMaterial, Vec3Arg inCharacterVelocity, Vec3 &ioNewCharacterVelocity)
Definition CharacterVirtual.h:87
virtual void OnAdjustBodyVelocity(const CharacterVirtual *inCharacter, const Body &inBody2, Vec3 &ioLinearVelocity, Vec3 &ioAngularVelocity)
Definition CharacterVirtual.h:63
This class contains settings that allow you to override the behavior of a character's collision respo...
Definition CharacterVirtual.h:48
bool mCanPushCharacter
True when the object can push the virtual character.
Definition CharacterVirtual.h:50
bool mCanReceiveImpulses
True when the virtual character can apply impulses (push) the body.
Definition CharacterVirtual.h:51
Definition CharacterVirtual.h:96
void SetUserData(uint64 inUserData)
Definition CharacterVirtual.h:176
float GetMass() const
Character mass (kg)
Definition CharacterVirtual.h:142
float GetPenetrationRecoverySpeed() const
This value governs how fast a penetration will be resolved, 0 = nothing is resolved,...
Definition CharacterVirtual.h:150
RVec3 GetPosition() const
Get the position of the character.
Definition CharacterVirtual.h:124
void SetLinearVelocity(Vec3Arg inLinearVelocity)
Set the linear velocity of the character (m / s)
Definition CharacterVirtual.h:121
const ContactList & GetActiveContacts() const
Access to the internal list of contacts that the character has found.
Definition CharacterVirtual.h:322
RMat44 GetWorldTransform() const
Calculate the world transform of the character.
Definition CharacterVirtual.h:136
std::vector< Contact, STLTempAllocator< Contact > > TempContactList
Definition CharacterVirtual.h:318
bool GetMaxHitsExceeded() const
Definition CharacterVirtual.h:168
void SetMaxStrength(float inMaxStrength)
Definition CharacterVirtual.h:147
float GetCharacterPadding() const
Character padding.
Definition CharacterVirtual.h:154
void SetMaxNumHits(uint inMaxHits)
Definition CharacterVirtual.h:158
uint GetMaxNumHits() const
Max num hits to collect in order to avoid excess of contact points collection.
Definition CharacterVirtual.h:157
float GetMaxStrength() const
Maximum force with which the character can push other bodies (N)
Definition CharacterVirtual.h:146
void SetShapeOffset(Vec3Arg inShapeOffset)
Definition CharacterVirtual.h:172
Array< Contact > ContactList
Definition CharacterVirtual.h:319
void SetMass(float inMass)
Definition CharacterVirtual.h:143
Vec3 GetLinearVelocity() const
Get the linear velocity of the character (m / s)
Definition CharacterVirtual.h:118
CharacterContactListener * GetListener() const
Get the current contact listener.
Definition CharacterVirtual.h:115
RMat44 GetCenterOfMassTransform() const
Calculates the transform for this character's center of mass.
Definition CharacterVirtual.h:139
CharacterVirtual(const CharacterVirtualSettings *inSettings, RVec3Arg inPosition, QuatArg inRotation, PhysicsSystem *inSystem)
Constructor without user data.
Definition CharacterVirtual.h:109
void SetRotation(QuatArg inRotation)
Set the rotation of the character.
Definition CharacterVirtual.h:133
void SetHitReductionCosMaxAngle(float inCosMaxAngle)
Definition CharacterVirtual.h:162
uint64 GetUserData() const
Access to the user data, can be used for anything by the application.
Definition CharacterVirtual.h:175
Vec3 GetShapeOffset() const
An extra offset applied to the shape in local space. This allows applying an extra offset to the shap...
Definition CharacterVirtual.h:171
void SetPenetrationRecoverySpeed(float inSpeed)
Definition CharacterVirtual.h:151
float GetHitReductionCosMaxAngle() const
Cos(angle) where angle is the maximum angle between two hits contact normals that are allowed to be m...
Definition CharacterVirtual.h:161
void SetPosition(RVec3Arg inPosition)
Set the position of the character.
Definition CharacterVirtual.h:127
void SetListener(CharacterContactListener *inListener)
Set the contact listener.
Definition CharacterVirtual.h:112
Quat GetRotation() const
Get the rotation of the character.
Definition CharacterVirtual.h:130
Contains the configuration of a character.
Definition CharacterVirtual.h:20
Class that contains all information of two colliding shapes.
Definition CollideShape.h:19
Virtual interface that allows collecting multiple collision results.
Definition CollisionCollector.h:45
Base class for all physics constraints. A constraint removes one or more degrees of freedom for a rig...
Definition Constraint.h:103
Holds a 4x4 matrix of floats, but supports also operations on the 3x3 upper left part of the matrix.
Definition Mat44.h:13
JPH_INLINE Mat44 PostTranslated(Vec3Arg inTranslation) const
Post multiply by translation matrix: result = Mat44::sTranslation(inTranslation) * this (i....
Definition Mat44.inl:903
JPH_INLINE Mat44 PreTranslated(Vec3Arg inTranslation) const
Pre multiply by translation matrix: result = this * Mat44::sTranslation(inTranslation)
Definition Mat44.inl:898
static JPH_INLINE Mat44 sRotationTranslation(QuatArg inR, Vec3Arg inT)
Get matrix that rotates and translates.
Definition Mat44.inl:149
Filter class for object layers.
Definition ObjectLayer.h:28
Definition PhysicsMaterial.h:23
Definition PhysicsSystem.h:29
An infinite plane described by the formula X . Normal + Constant = 0.
Definition Plane.h:11
Definition Quat.h:33
static JPH_INLINE Quat sIdentity()
Definition Quat.h:103
Result of a shape cast test.
Definition ShapeCast.h:111
Filter class.
Definition ShapeFilter.h:17
Base class for all shapes (collision volume of a body). Defines a virtual interface for collision det...
Definition Shape.h:178
Definition StateRecorder.h:48
A sub shape id contains a path to an element (usually a triangle or other primitive type) of a compou...
Definition SubShapeID.h:23
Definition TempAllocator.h:16
Definition Vec3.h:16
static JPH_INLINE Vec3 sZero()
Vector with all zeros.
Definition Vec3.inl:107
Definition CharacterVirtual.h:296
EMotionType mMotionTypeB
Motion type of B, used to determine the priority of the contact.
Definition CharacterVirtual.h:309
Vec3 mContactNormal
Contact normal, pointing towards the character.
Definition CharacterVirtual.h:303
const PhysicsMaterial * mMaterial
Material of B.
Definition CharacterVirtual.h:312
float mFraction
Fraction along the path where this contact takes place.
Definition CharacterVirtual.h:306
uint64 mUserData
User data of B.
Definition CharacterVirtual.h:311
BodyID mBodyB
ID of body we're colliding with.
Definition CharacterVirtual.h:307
SubShapeID mSubShapeIDB
Sub shape ID of body we're colliding with.
Definition CharacterVirtual.h:308
Vec3 mLinearVelocity
Velocity of the contact point.
Definition CharacterVirtual.h:302
float mDistance
Distance to the contact <= 0 means that it is an actual contact, > 0 means predictive.
Definition CharacterVirtual.h:305
Vec3 mSurfaceNormal
Surface normal of the contact.
Definition CharacterVirtual.h:304
RVec3 mPosition
Position where the character makes contact.
Definition CharacterVirtual.h:301
bool mIsSensorB
If B is a sensor.
Definition CharacterVirtual.h:310
Settings struct with settings for ExtendedUpdate.
Definition CharacterVirtual.h:229