Jolt Physics
A multi core friendly Game Physics Engine
Loading...
Searching...
No Matches
VehicleConstraint Class Reference

#include <VehicleConstraint.h>

Inheritance diagram for VehicleConstraint:
Constraint PhysicsStepListener RefTarget< Constraint > NonCopyable

Public Types

using CombineFunction = function< void(uint inWheelIndex, float &ioLongitudinalFriction, float &ioLateralFriction, const Body &inBody2, const SubShapeID &inSubShapeID2)>
 
using StepCallback = function< void(VehicleConstraint &inVehicle, float inDeltaTime, PhysicsSystem &inPhysicsSystem)>
 Callback function to notify of current stage in PhysicsStepListener::OnStep.
 

Public Member Functions

 VehicleConstraint (Body &inVehicleBody, const VehicleConstraintSettings &inSettings)
 Constructor / destructor.
 
virtual ~VehicleConstraint () override
 
virtual EConstraintSubType GetSubType () const override
 Get the type of a constraint.
 
void SetMaxPitchRollAngle (float inMaxPitchRollAngle)
 Defines the maximum pitch/roll angle (rad), can be used to avoid the car from getting upside down. The vehicle up direction will stay within a cone centered around the up axis with half top angle mMaxPitchRollAngle, set to pi to turn off.
 
void SetVehicleCollisionTester (const VehicleCollisionTester *inTester)
 Set the interface that tests collision between wheel and ground.
 
void SetCombineFriction (const CombineFunction &inCombineFriction)
 
const CombineFunctionGetCombineFriction () const
 
const StepCallbackGetPreStepCallback () const
 
void SetPreStepCallback (const StepCallback &inPreStepCallback)
 
const StepCallbackGetPostCollideCallback () const
 
void SetPostCollideCallback (const StepCallback &inPostCollideCallback)
 
const StepCallbackGetPostStepCallback () const
 
void SetPostStepCallback (const StepCallback &inPostStepCallback)
 
Vec3 GetLocalForward () const
 Get the local space forward vector of the vehicle.
 
Vec3 GetLocalUp () const
 Get the local space up vector of the vehicle.
 
Vec3 GetWorldUp () const
 Vector indicating the world space up direction (used to limit vehicle pitch/roll), calculated every frame by inverting gravity.
 
BodyGetVehicleBody () const
 Access to the vehicle body.
 
const VehicleControllerGetController () const
 Access to the vehicle controller interface (determines acceleration / deceleration)
 
VehicleControllerGetController ()
 Access to the vehicle controller interface (determines acceleration / deceleration)
 
const WheelsGetWheels () const
 Get the state of the wheels.
 
WheelsGetWheels ()
 Get the state of a wheels (writable interface, allows you to make changes to the configuration which will take effect the next time step)
 
WheelGetWheel (uint inIdx)
 Get the state of a wheel.
 
const WheelGetWheel (uint inIdx) const
 
void GetWheelLocalBasis (const Wheel *inWheel, Vec3 &outForward, Vec3 &outUp, Vec3 &outRight) const
 
Mat44 GetWheelLocalTransform (uint inWheelIndex, Vec3Arg inWheelRight, Vec3Arg inWheelUp) const
 
RMat44 GetWheelWorldTransform (uint inWheelIndex, Vec3Arg inWheelRight, Vec3Arg inWheelUp) const
 
void SetNumStepsBetweenCollisionTestActive (uint inSteps)
 
uint GetNumStepsBetweenCollisionTestActive () const
 
void SetNumStepsBetweenCollisionTestInactive (uint inSteps)
 
uint GetNumStepsBetweenCollisionTestInactive () const
 
virtual bool IsActive () const override
 
virtual void NotifyShapeChanged (const BodyID &inBodyID, Vec3Arg inDeltaCOM) override
 
virtual void SetupVelocityConstraint (float inDeltaTime) override
 
virtual void ResetWarmStart () override
 
virtual void WarmStartVelocityConstraint (float inWarmStartImpulseRatio) override
 
virtual bool SolveVelocityConstraint (float inDeltaTime) override
 
virtual bool SolvePositionConstraint (float inDeltaTime, float inBaumgarte) override
 
virtual void BuildIslands (uint32 inConstraintIndex, IslandBuilder &ioBuilder, BodyManager &inBodyManager) override
 Link bodies that are connected by this constraint in the island builder.
 
virtual uint BuildIslandSplits (LargeIslandSplitter &ioSplitter) const override
 Link bodies that are connected by this constraint in the same split. Returns the split index.
 
virtual void DrawConstraint (DebugRenderer *inRenderer) const override
 
virtual void DrawConstraintLimits (DebugRenderer *inRenderer) const override
 
virtual void SaveState (StateRecorder &inStream) const override
 Saving state for replay.
 
virtual void RestoreState (StateRecorder &inStream) override
 Restoring state for replay.
 
virtual Ref< ConstraintSettingsGetConstraintSettings () const override
 Debug function to convert a constraint to its settings, note that this will not save to which bodies the constraint is connected to.
 
- Public Member Functions inherited from Constraint
JPH_OVERRIDE_NEW_DELETE Constraint (const ConstraintSettings &inSettings)
 Constructor.
 
virtual ~Constraint ()=default
 Virtual destructor.
 
virtual EConstraintType GetType () const
 Get the type of a constraint.
 
uint32 GetConstraintPriority () const
 
void SetConstraintPriority (uint32 inPriority)
 
void SetNumVelocityStepsOverride (uint inN)
 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.
 
uint GetNumVelocityStepsOverride () const
 
void SetNumPositionStepsOverride (uint inN)
 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.
 
uint GetNumPositionStepsOverride () const
 
void SetEnabled (bool inEnabled)
 
bool GetEnabled () const
 Test if a constraint is enabled.
 
uint64 GetUserData () const
 Access to the user data, can be used for anything by the application.
 
void SetUserData (uint64 inUserData)
 
virtual void DrawConstraintReferenceFrame (DebugRenderer *inRenderer) const
 
float GetDrawConstraintSize () const
 Size of constraint when drawing it through the debug renderer.
 
void SetDrawConstraintSize (float inSize)
 
- Public Member Functions inherited from RefTarget< Constraint >
 RefTarget ()=default
 Constructor.
 
 RefTarget (const RefTarget &)
 
 ~RefTarget ()
 assert no one is referencing us
 
void SetEmbedded () const
 
RefTargetoperator= (const RefTarget &)
 Assignment operator.
 
uint32 GetRefCount () const
 Get current refcount of this object.
 
void AddRef () const
 Add or release a reference to this object.
 
void Release () const
 
- Public Member Functions inherited from NonCopyable
 NonCopyable ()=default
 
 NonCopyable (const NonCopyable &)=delete
 
void operator= (const NonCopyable &)=delete
 
- Public Member Functions inherited from PhysicsStepListener
virtual ~PhysicsStepListener ()=default
 Ensure virtual destructor.
 

Additional Inherited Members

- Static Public Member Functions inherited from RefTarget< Constraint >
static int sInternalGetRefCountOffset ()
 INTERNAL HELPER FUNCTION USED BY SERIALIZATION.
 
- Protected Member Functions inherited from Constraint
void ToConstraintSettings (ConstraintSettings &outSettings) const
 Helper function to copy settings back to constraint settings for this base class.
 
- Protected Attributes inherited from Constraint
float mDrawConstraintSize
 Size of constraint when drawing it through the debug renderer.
 
- Protected Attributes inherited from RefTarget< Constraint >
atomic< uint32mRefCount
 Current reference count.
 
- Static Protected Attributes inherited from RefTarget< Constraint >
static constexpr uint32 cEmbedded
 A large value that gets added to the refcount to mark the object as embedded.
 

Detailed Description

Constraint that simulates a vehicle Note: Don't forget to register the constraint as a StepListener with the PhysicsSystem!

When the vehicle drives over very light objects (rubble) you may see the car body dip down. This is a known issue and is an artifact of the iterative solver that Jolt is using. Basically if a light object is sandwiched between two heavy objects (the static floor and the car body), the light object is not able to transfer enough force from the ground to the car body to keep the car body up. You can see this effect in the HeavyOnLightTest sample, the boxes on the right have a lot of penetration because they're on top of light objects.

There are a couple of ways to improve this:

  1. You can increase the number of velocity steps (global settings PhysicsSettings::mNumVelocitySteps or if you only want to increase it on the vehicle you can use VehicleConstraintSettings::mNumVelocityStepsOverride). E.g. going from 10 to 30 steps in the HeavyOnLightTest sample makes the penetration a lot less. The number of position steps can also be increased (the first prevents the body from going down, the second corrects it if the problem did occur which inevitably happens due to numerical drift). This solution costs CPU cycles.
  2. You can reduce the mass difference between the vehicle body and the rubble on the floor (by making the rubble heavier or the car lighter).
  3. You could filter out collisions between the vehicle collision test and the rubble completely. This would make the wheels ignore the rubble but would cause the vehicle to drive through it as if nothing happened. You could create fake wheels (keyframed bodies) that move along with the vehicle and that only collide with rubble (and not the vehicle or the ground). This would cause the vehicle to push away the rubble without the rubble being able to affect the vehicle (unless it hits the main body of course).

Note that when driving over rubble, you may see the wheel jump up and down quite quickly because one frame a collision is found and the next frame not. To alleviate this, it may be needed to smooth the motion of the visual mesh for the wheel.

Member Typedef Documentation

◆ CombineFunction

using VehicleConstraint::CombineFunction = function<void(uint inWheelIndex, float &ioLongitudinalFriction, float &ioLateralFriction, const Body &inBody2, const SubShapeID &inSubShapeID2)>

Callback function to combine the friction of a tire with the friction of the body it is colliding with. On input ioLongitudinalFriction and ioLateralFriction contain the friction of the tire, on output they should contain the combined friction with inBody2.

◆ StepCallback

using VehicleConstraint::StepCallback = function<void(VehicleConstraint &inVehicle, float inDeltaTime, PhysicsSystem &inPhysicsSystem)>

Callback function to notify of current stage in PhysicsStepListener::OnStep.

Constructor & Destructor Documentation

◆ VehicleConstraint()

VehicleConstraint::VehicleConstraint ( Body inVehicleBody,
const VehicleConstraintSettings inSettings 
)

Constructor / destructor.

◆ ~VehicleConstraint()

VehicleConstraint::~VehicleConstraint ( )
overridevirtual

Member Function Documentation

◆ BuildIslands()

void VehicleConstraint::BuildIslands ( uint32  inConstraintIndex,
IslandBuilder ioBuilder,
BodyManager inBodyManager 
)
overridevirtual

Link bodies that are connected by this constraint in the island builder.

Implements Constraint.

◆ BuildIslandSplits()

uint VehicleConstraint::BuildIslandSplits ( LargeIslandSplitter ioSplitter) const
overridevirtual

Link bodies that are connected by this constraint in the same split. Returns the split index.

Implements Constraint.

◆ DrawConstraint()

void VehicleConstraint::DrawConstraint ( DebugRenderer inRenderer) const
overridevirtual

Implements Constraint.

◆ DrawConstraintLimits()

void VehicleConstraint::DrawConstraintLimits ( DebugRenderer inRenderer) const
overridevirtual

Reimplemented from Constraint.

◆ GetCombineFriction()

const CombineFunction & VehicleConstraint::GetCombineFriction ( ) const
inline

◆ GetConstraintSettings()

Ref< ConstraintSettings > VehicleConstraint::GetConstraintSettings ( ) const
overridevirtual

Debug function to convert a constraint to its settings, note that this will not save to which bodies the constraint is connected to.

Implements Constraint.

◆ GetController() [1/2]

VehicleController * VehicleConstraint::GetController ( )
inline

Access to the vehicle controller interface (determines acceleration / deceleration)

◆ GetController() [2/2]

const VehicleController * VehicleConstraint::GetController ( ) const
inline

Access to the vehicle controller interface (determines acceleration / deceleration)

◆ GetLocalForward()

Vec3 VehicleConstraint::GetLocalForward ( ) const
inline

Get the local space forward vector of the vehicle.

◆ GetLocalUp()

Vec3 VehicleConstraint::GetLocalUp ( ) const
inline

Get the local space up vector of the vehicle.

◆ GetNumStepsBetweenCollisionTestActive()

uint VehicleConstraint::GetNumStepsBetweenCollisionTestActive ( ) const
inline

◆ GetNumStepsBetweenCollisionTestInactive()

uint VehicleConstraint::GetNumStepsBetweenCollisionTestInactive ( ) const
inline

◆ GetPostCollideCallback()

const StepCallback & VehicleConstraint::GetPostCollideCallback ( ) const
inline

Callback function to notify that PhysicsStepListener::OnStep has just completed wheel collision checks. Default is to do nothing. Can be used to allow higher-level code to e.g. detect tire contact or to modify the velocity of the vehicle based on the wheel contacts. You should not change the position of the vehicle in this callback as the wheel collision checks have already been performed.

◆ GetPostStepCallback()

const StepCallback & VehicleConstraint::GetPostStepCallback ( ) const
inline

Callback function to notify that PhysicsStepListener::OnStep has completed for this vehicle. Default is to do nothing. Can be used to allow higher-level code to e.g. control the vehicle in the air. You should not change the position of the vehicle in this callback as the wheel collision checks have already been performed.

◆ GetPreStepCallback()

const StepCallback & VehicleConstraint::GetPreStepCallback ( ) const
inline

Callback function to notify that PhysicsStepListener::OnStep has started for this vehicle. Default is to do nothing. Can be used to allow higher-level code to e.g. control steering. This is the last moment that the position/orientation of the vehicle can be changed. Wheel collision checks have not been performed yet.

◆ GetSubType()

virtual EConstraintSubType VehicleConstraint::GetSubType ( ) const
inlineoverridevirtual

Get the type of a constraint.

Implements Constraint.

◆ GetVehicleBody()

Body * VehicleConstraint::GetVehicleBody ( ) const
inline

Access to the vehicle body.

◆ GetWheel() [1/2]

Wheel * VehicleConstraint::GetWheel ( uint  inIdx)
inline

Get the state of a wheel.

◆ GetWheel() [2/2]

const Wheel * VehicleConstraint::GetWheel ( uint  inIdx) const
inline

◆ GetWheelLocalBasis()

void VehicleConstraint::GetWheelLocalBasis ( const Wheel inWheel,
Vec3 outForward,
Vec3 outUp,
Vec3 outRight 
) const

Get the basis vectors for the wheel in local space to the vehicle body (note: basis does not rotate when the wheel rotates around its axis)

Parameters
inWheelWheel to fetch basis for
outForwardForward vector for the wheel
outUpUp vector for the wheel
outRightRight vector for the wheel

◆ GetWheelLocalTransform()

Mat44 VehicleConstraint::GetWheelLocalTransform ( uint  inWheelIndex,
Vec3Arg  inWheelRight,
Vec3Arg  inWheelUp 
) const

Get the transform of a wheel in local space to the vehicle body, returns a matrix that transforms a cylinder aligned with the Y axis in body space (not COM space)

Parameters
inWheelIndexIndex of the wheel to fetch
inWheelRightUnit vector that indicates right in model space of the wheel (so if you only have 1 wheel model, you probably want to specify the opposite direction for the left and right wheels)
inWheelUpUnit vector that indicates up in model space of the wheel

◆ GetWheels() [1/2]

Wheels & VehicleConstraint::GetWheels ( )
inline

Get the state of a wheels (writable interface, allows you to make changes to the configuration which will take effect the next time step)

◆ GetWheels() [2/2]

const Wheels & VehicleConstraint::GetWheels ( ) const
inline

Get the state of the wheels.

◆ GetWheelWorldTransform()

RMat44 VehicleConstraint::GetWheelWorldTransform ( uint  inWheelIndex,
Vec3Arg  inWheelRight,
Vec3Arg  inWheelUp 
) const

Get the transform of a wheel in world space, returns a matrix that transforms a cylinder aligned with the Y axis in world space

Parameters
inWheelIndexIndex of the wheel to fetch
inWheelRightUnit vector that indicates right in model space of the wheel (so if you only have 1 wheel model, you probably want to specify the opposite direction for the left and right wheels)
inWheelUpUnit vector that indicates up in model space of the wheel

◆ GetWorldUp()

Vec3 VehicleConstraint::GetWorldUp ( ) const
inline

Vector indicating the world space up direction (used to limit vehicle pitch/roll), calculated every frame by inverting gravity.

◆ IsActive()

virtual bool VehicleConstraint::IsActive ( ) const
inlineoverridevirtual

Reimplemented from Constraint.

◆ NotifyShapeChanged()

virtual void VehicleConstraint::NotifyShapeChanged ( const BodyID inBodyID,
Vec3Arg  inDeltaCOM 
)
inlineoverridevirtual

Notify the constraint that the shape of a body has changed and that its center of mass has moved by inDeltaCOM. Bodies don't know which constraints are connected to them so the user is responsible for notifying the relevant constraints when a body changes.

Parameters
inBodyIDID of the body that has changed
inDeltaCOMThe delta of the center of mass of the body (shape->GetCenterOfMass() - shape_before_change->GetCenterOfMass())

Implements Constraint.

◆ ResetWarmStart()

void VehicleConstraint::ResetWarmStart ( )
overridevirtual

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. 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 that 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 changes 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).

Implements Constraint.

◆ RestoreState()

void VehicleConstraint::RestoreState ( StateRecorder inStream)
overridevirtual

Restoring state for replay.

Reimplemented from Constraint.

◆ SaveState()

void VehicleConstraint::SaveState ( StateRecorder inStream) const
overridevirtual

Saving state for replay.

Reimplemented from Constraint.

◆ SetCombineFriction()

void VehicleConstraint::SetCombineFriction ( const CombineFunction inCombineFriction)
inline

Set the function that combines the friction of two bodies and returns it Default method is the geometric mean: sqrt(friction1 * friction2).

◆ SetMaxPitchRollAngle()

void VehicleConstraint::SetMaxPitchRollAngle ( float  inMaxPitchRollAngle)
inline

Defines the maximum pitch/roll angle (rad), can be used to avoid the car from getting upside down. The vehicle up direction will stay within a cone centered around the up axis with half top angle mMaxPitchRollAngle, set to pi to turn off.

◆ SetNumStepsBetweenCollisionTestActive()

void VehicleConstraint::SetNumStepsBetweenCollisionTestActive ( uint  inSteps)
inline

Number of simulation steps between wheel collision tests when the vehicle is active. Default is 1. 0 = never, 1 = every step, 2 = every other step, etc. Note that if a vehicle has multiple wheels and the number of steps > 1, the wheels will be tested in a round robin fashion. If there are multiple vehicles, the tests will be spread out based on the BodyID of the vehicle. If you set this to test less than every step, you may see simulation artifacts. This setting can be used to reduce the cost of simulating vehicles in the distance.

◆ SetNumStepsBetweenCollisionTestInactive()

void VehicleConstraint::SetNumStepsBetweenCollisionTestInactive ( uint  inSteps)
inline

Number of simulation steps between wheel collision tests when the vehicle is inactive. Default is 1. 0 = never, 1 = every step, 2 = every other step, etc. Note that if a vehicle has multiple wheels and the number of steps > 1, the wheels will be tested in a round robin fashion. If there are multiple vehicles, the tests will be spread out based on the BodyID of the vehicle. This number can be lower than the number of steps when the vehicle is active as the only purpose of this test is to allow the vehicle to wake up in response to bodies moving into the wheels but not touching the body of the vehicle.

◆ SetPostCollideCallback()

void VehicleConstraint::SetPostCollideCallback ( const StepCallback inPostCollideCallback)
inline

◆ SetPostStepCallback()

void VehicleConstraint::SetPostStepCallback ( const StepCallback inPostStepCallback)
inline

◆ SetPreStepCallback()

void VehicleConstraint::SetPreStepCallback ( const StepCallback inPreStepCallback)
inline

◆ SetupVelocityConstraint()

void VehicleConstraint::SetupVelocityConstraint ( float  inDeltaTime)
overridevirtual

Implements Constraint.

◆ SetVehicleCollisionTester()

void VehicleConstraint::SetVehicleCollisionTester ( const VehicleCollisionTester inTester)
inline

Set the interface that tests collision between wheel and ground.

◆ SolvePositionConstraint()

bool VehicleConstraint::SolvePositionConstraint ( float  inDeltaTime,
float  inBaumgarte 
)
overridevirtual

Implements Constraint.

◆ SolveVelocityConstraint()

bool VehicleConstraint::SolveVelocityConstraint ( float  inDeltaTime)
overridevirtual

Implements Constraint.

◆ WarmStartVelocityConstraint()

void VehicleConstraint::WarmStartVelocityConstraint ( float  inWarmStartImpulseRatio)
overridevirtual

Implements Constraint.


The documentation for this class was generated from the following files: