Class World
- Namespace
- Jitter2
- Assembly
- Jitter2.dll
Represents a simulation environment that holds and manages the state of all simulation objects.
public sealed class World : IDisposable
- Inheritance
-
World
- Implements
- Inherited Members
Constructors
World()
Creates an instance of the World class.
public World()
Properties
AllowDeactivation
Specifies whether the deactivation mechanism of Jitter is enabled. Does not activate inactive objects if set to false.
public bool AllowDeactivation { get; set; }
Property Value
BroadPhaseFilter
Hook into the broadphase collision detection pipeline. The default value is null.
public IBroadPhaseFilter? BroadPhaseFilter { get; set; }
Property Value
Remarks
Use this to intercept shape pairs before narrow-phase detection, implement custom collision layers,
or handle collisions for custom proxy types. When Step(float, bool) is called
with multiThread=true, this may be invoked concurrently. Implementations must be thread-safe.
DebugTimings
Contains timings for the stages of the last call to Step(float, bool).
Values are in milliseconds. Index using (int)Timings.XYZ.
public ReadOnlySpan<double> DebugTimings { get; }
Property Value
DynamicTree
Access to the DynamicTree instance. The instance should only be modified by Jitter.
public DynamicTree DynamicTree { get; }
Property Value
EnableAuxiliaryContactPoints
Enables the generation of additional contacts for flat surfaces that are in contact. Traditionally, the collision system reports the deepest collision point between two objects. A full contact manifold is then generated over several time steps using contact caching, which can be unstable. This method attempts to build a fuller or complete contact manifold within a single time step.
public bool EnableAuxiliaryContactPoints { get; set; }
Property Value
Gravity
Default gravity, see also AffectedByGravity. Default value: (0, -9.81, 0).
public JVector Gravity { get; set; }
Property Value
Islands
All collision islands in this world.
public ReadOnlyPartitionedSet<Island> Islands { get; }
Property Value
NarrowPhaseFilter
Hook into the narrow-phase collision detection pipeline. The default instance is of type TriangleEdgeCollisionFilter.
public INarrowPhaseFilter? NarrowPhaseFilter { get; set; }
Property Value
Remarks
Use this to intercept collisions after contact generation, modify contact data,
or implement custom collision responses. When Step(float, bool) is called
with multiThread=true, this may be invoked concurrently. Implementations must be thread-safe.
NullBody
A fixed body, pinned to the world. Can be used to create constraints with.
public RigidBody NullBody { get; }
Property Value
RawData
Grants access to objects residing in unmanaged memory. This operation can be potentially unsafe. Use the corresponding managed properties where possible to mitigate risk.
public World.SpanData RawData { get; }
Property Value
RigidBodies
All rigid bodies in this world.
public ReadOnlyPartitionedSet<RigidBody> RigidBodies { get; }
Property Value
SolverIterations
Gets or sets the number of iterations per substep for the constraint solver and velocity relaxation.
public (int solver, int relaxation) SolverIterations { get; set; }
Property Value
- (int solver, int relaxation)
Remarks
Higher solver iterations improve constraint accuracy at the cost of performance. Relaxation iterations help reduce velocity errors after solving. Default value: (solver: 6, relaxation: 4).
Exceptions
- ArgumentException
Thrown if
solveris less than 1 orrelaxationis negative.
SpeculativeRelaxationFactor
A speculative contact slows a body down such that it does not penetrate or tunnel through an obstacle within one frame. The SpeculativeRelaxationFactor scales the slowdown, ranging from 0 (where the body stops immediately during this frame) to 1 (where the body and the obstacle just touch after the next velocity integration). A value below 1 is preferred, as the leftover velocity might be enough to trigger another speculative contact in the next frame. Default value: 0.9.
public float SpeculativeRelaxationFactor { get; set; }
Property Value
SpeculativeVelocityThreshold
Speculative contacts are generated when the relative velocity between two bodies exceeds the threshold value. To prevent bodies with a diameter of D from tunneling through thin walls, this threshold should be set to approximately D / timestep, e.g., 100 for a unit cube and a timestep of 0.01. Default value: 10.0.
public float SpeculativeVelocityThreshold { get; set; }
Property Value
SubstepCount
The number of substeps for each call to Step(float, bool). Sub-stepping is deactivated when set to one. Default value: 1.
public int SubstepCount { get; set; }
Property Value
ThreadModel
Defines the two available thread models. The Persistent model keeps the worker threads active continuously, even when the Step(float, bool) is not in operation, which might consume more CPU cycles and possibly affect the performance of other operations such as rendering. However, it ensures that the threads remain 'warm' for the next invocation of Step(float, bool). Conversely, the Regular model allows the worker threads to yield and undertake other tasks.
public World.ThreadModelType ThreadModel { get; set; }
Property Value
Methods
Clear()
Removes all entities from the simulation world. Also clears all proxies from the dynamic tree, including any user-added proxies not owned by the world.
public void Clear()
CreateConstraint<T>(RigidBody, RigidBody)
Constructs a constraint of the specified type. After creation, initialize the constraint
by calling its Initialize method.
public T CreateConstraint<T>(RigidBody body1, RigidBody body2) where T : Constraint, new()
Parameters
body1RigidBodyThe first rigid body involved in the constraint.
body2RigidBodyThe second rigid body involved in the constraint.
Returns
- T
A new instance of the specified constraint type, already registered with the world.
Type Parameters
TThe specific type of constraint to create.
Exceptions
- ArgumentException
Thrown if
body1andbody2are the same.- PartitionedBuffer<T>.MaximumSizeException
Raised when the maximum size limit is exceeded.
CreateRigidBody()
Creates and adds a new rigid body to the simulation world.
public RigidBody CreateRigidBody()
Returns
Exceptions
- PartitionedBuffer<T>.MaximumSizeException
Raised when the maximum size limit is exceeded.
DefaultDynamicTreeFilter(IDynamicTreeProxy, IDynamicTreeProxy)
Default filter function for the DynamicTree. Returns true if both proxies are of type RigidBodyShape and belong to different RigidBody instances.
public static bool DefaultDynamicTreeFilter(IDynamicTreeProxy proxyA, IDynamicTreeProxy proxyB)
Parameters
proxyAIDynamicTreeProxyproxyBIDynamicTreeProxy
Returns
Dispose()
Releases all unmanaged memory buffers used by this simulation world.
public void Dispose()
Remarks
After disposal, the world instance is unusable. All bodies, constraints, and contacts become invalid. Calling Dispose() multiple times is safe.
GetArbiter(ulong, ulong, out Arbiter)
Retrieves an existing Arbiter instance for the given pair of IDs.
public bool GetArbiter(ulong id0, ulong id1, out Arbiter arbiter)
Parameters
id0ulongThe first identifier (e.g., shape ID).
id1ulongThe second identifier.
arbiterArbiterWhen this method returns true, contains the arbiter; otherwise, null.
Returns
Remarks
The order of id0 and id1 matters.
For arbiters created by the engine, id0 < id1 holds
for RigidBodyShapes.
GetOrCreateArbiter(ulong, ulong, RigidBody, RigidBody, out Arbiter)
Retrieves an existing Arbiter instance for the given pair of IDs, or creates a new one if none exists.
public void GetOrCreateArbiter(ulong id0, ulong id1, RigidBody body1, RigidBody body2, out Arbiter arbiter)
Parameters
id0ulongThe first identifier associated with the contact (e.g., shape or feature ID).
id1ulongThe second identifier associated with the contact.
body1RigidBodyThe first rigid body. Used only if a new arbiter is created.
body2RigidBodyThe second rigid body. Used only if a new arbiter is created.
arbiterArbiterThe resulting Arbiter instance associated with the ID pair.
Remarks
This method ensures there is a unique Arbiter for each ordered pair of IDs.
If an arbiter already exists, it is returned via the arbiter out parameter.
Otherwise, a new arbiter is allocated, initialized with the provided body1 and body2,
and registered internally. The body arguments are used only when a new arbiter is created.
This method is thread-safe.
Note: The order of id0 and id1 does matter.
LockTwoBody(ref RigidBodyData, ref RigidBodyData)
Acquires locks on two rigid bodies using a spin-wait loop. The lock order is determined by memory address to prevent deadlocks.
public static void LockTwoBody(ref RigidBodyData b1, ref RigidBodyData b2)
Parameters
b1RigidBodyDataReference to the first rigid body data.
b2RigidBodyDataReference to the second rigid body data.
RegisterContact(Arbiter, in JVector, in JVector, in JVector, SolveMode)
Registers a single contact point into an existing Arbiter.
public void RegisterContact(Arbiter arbiter, in JVector point1, in JVector point2, in JVector normal, ContactData.SolveMode removeFlags = SolveMode.None)
Parameters
arbiterArbiterThe existing Arbiter instance to which the contact will be added.
point1JVectorThe contact point on the first body, in world space.
point2JVectorThe contact point on the second body, in world space.
normalJVectorThe contact normal, in world space. Must be normalized.
removeFlagsContactData.SolveModeA bitmask of ContactData.SolveMode flags to be removed from the full contact solution (see Full).
Remarks
This method adds a contact point to the specified arbiter, using the provided contact points
and normal. All input vectors must be in world space. The normal vector must be normalized.
This method assumes that the arbiter is already valid and mapped to the correct pair of bodies.
RegisterContact(ulong, ulong, RigidBody, RigidBody, in JVector, ref CollisionManifold, SolveMode)
Registers one or more contact points between two rigid bodies using a CollisionManifold, creating an Arbiter if one does not already exist.
public void RegisterContact(ulong id0, ulong id1, RigidBody body1, RigidBody body2, in JVector normal, ref CollisionManifold manifold, ContactData.SolveMode removeFlags = SolveMode.None)
Parameters
id0ulongThe first identifier associated with the contact (e.g., shape or feature ID).
id1ulongThe second identifier associated with the contact.
body1RigidBodyThe first rigid body involved in the contact.
body2RigidBodyThe second rigid body involved in the contact.
normalJVectorThe contact normal, in world space. Must be a unit vector pointing from
body1towardbody2.manifoldCollisionManifoldA CollisionManifold containing contact point pairs in world space.
removeFlagsContactData.SolveModeA bitmask of ContactData.SolveMode flags to be removed from the full contact solution (see Full).
Remarks
This method ensures that contact information between the specified ID pair is tracked by an Arbiter.
If no arbiter exists for the given IDs, one is created using body1 and body2.
This method is thread-safe.
Note: The order of id0 and id1 does matter.
RegisterContact(ulong, ulong, RigidBody, RigidBody, in JVector, in JVector, in JVector, SolveMode)
Registers a contact point between two rigid bodies, creating an Arbiter if one does not already exist.
public void RegisterContact(ulong id0, ulong id1, RigidBody body1, RigidBody body2, in JVector point1, in JVector point2, in JVector normal, ContactData.SolveMode removeFlags = SolveMode.None)
Parameters
id0ulongThe first identifier associated with the contact (e.g., shape or feature ID).
id1ulongThe second identifier associated with the contact.
body1RigidBodyThe first rigid body involved in the contact.
body2RigidBodyThe second rigid body involved in the contact.
point1JVectorThe contact point on
body1, in world space.point2JVectorThe contact point on
body2, in world space.normalJVectorThe contact normal, in world space. Must be a unit vector pointing from
body1towardbody2.removeFlagsContactData.SolveModeA bitmask of ContactData.SolveMode flags to be removed from the full contact solution (see Full).
Remarks
This method ensures that contact information between the specified ID pair is tracked by an Arbiter.
If no arbiter exists for the given IDs, one is created using body1 and body2.
The provided contact points and normal must be in world space. The normal vector must be normalized.
This method is thread-safe.
Note: The order of id0 and id1 does matter.
Remove(Arbiter)
Removes a particular arbiter from the world.
public void Remove(Arbiter arbiter)
Parameters
arbiterArbiter
Remove(Constraint)
Removes a specific constraint from the world. For temporary deactivation of constraints, consider using the IsEnabled property.
public void Remove(Constraint constraint)
Parameters
constraintConstraintThe constraint to be removed.
Remove(RigidBody)
Removes the specified body from the world. This operation also automatically discards any associated contacts and constraints.
public void Remove(RigidBody body)
Parameters
bodyRigidBodyThe rigid body to remove.
RequestId()
Generates a unique ID.
public static ulong RequestId()
Returns
- ulong
A monotonically increasing unique identifier.
RequestId(int)
Generates a range of unique IDs.
public static (ulong min, ulong max) RequestId(int count)
Parameters
countintThe number of IDs to generate.
Returns
- (ulong min, ulong max)
A tuple containing the minimum and maximum request IDs in the generated range. The upper bound is exclusive.
Exceptions
- ArgumentOutOfRangeException
Thrown when count is less than 1.
Stabilize(float, int, int, bool)
Solves the existing contacts and constraints at the velocity level without advancing body transforms.
public void Stabilize(float dt, int solverIterations, int relaxationIterations = 0, bool multiThread = true)
Parameters
dtfloatThe reference timestep in seconds used to scale bias and softness terms.
solverIterationsintThe number of solver iterations to execute.
relaxationIterationsintThe number of relaxation iterations to execute after solving.
multiThreadboolIf true, uses the internal thread pool for parallel execution.
Remarks
Unlike Step(float, bool), this method does not perform broadphase or narrowphase collision detection, does not integrate forces, and does not integrate positions or orientations. It only processes the existing active contacts and constraints already present in the world at the velocity level. This is primarily useful after loading a previously saved scene: restore the saved contacts and constraints first, then call Stabilize(float, int, int, bool) to warm-start and solve the restored system before resuming normal simulation with Step(float, bool).
Exceptions
- ArgumentException
Thrown if
dtis negative,solverIterationsis less than 1, orrelaxationIterationsis negative.
Step(float, bool)
Performs a single simulation step.
public void Step(float dt, bool multiThread = true)
Parameters
dtfloatThe duration of time to simulate in seconds. Should remain fixed and typically not exceed 1/60 s.
multiThreadboolIf true, uses the internal thread pool for parallel execution. Set to false for single-threaded execution (useful for debugging or platforms without threading).
Remarks
The step is divided into SubstepCount substeps for improved stability.
Callbacks (PreStep, PostStep, etc.) are invoked on the calling thread.
When multiThread is true, BroadPhaseFilter and NarrowPhaseFilter
may be called concurrently from worker threads.
Exceptions
- ArgumentException
Thrown if
dtis negative.
TryLockTwoBody(ref RigidBodyData, ref RigidBodyData)
Attempts to lock two rigid bodies. Briefly waits on contention, then backs off if unsuccessful. The lock order is determined by memory address to prevent deadlocks.
public static bool TryLockTwoBody(ref RigidBodyData b1, ref RigidBodyData b2)
Parameters
b1RigidBodyDataReference to the first rigid body data.
b2RigidBodyDataReference to the second rigid body data.
Returns
UnlockTwoBody(ref RigidBodyData, ref RigidBodyData)
Releases locks on two rigid bodies previously acquired by LockTwoBody(ref RigidBodyData, ref RigidBodyData) or TryLockTwoBody(ref RigidBodyData, ref RigidBodyData).
public static void UnlockTwoBody(ref RigidBodyData b1, ref RigidBodyData b2)
Parameters
b1RigidBodyDataReference to the first rigid body data.
b2RigidBodyDataReference to the second rigid body data.
Events
PostStep
Raised at the end of a simulation step, after all substeps, collision handling, and integration have completed.
[CallbackThread(ThreadContext.MainThread)]
public event World.WorldStep? PostStep
Event Type
Remarks
This event is invoked once per call to Step(float, bool) and receives the full
step time dt. At this point, all body states represent the final results
of the step.
PostSubStep
Raised at the end of each substep during a simulation step.
[CallbackThread(ThreadContext.MainThread)]
public event World.WorldStep? PostSubStep
Event Type
Remarks
This event is invoked once per substep and receives the substep duration. It is called after integration and constraint solving for the substep have completed.
PreStep
Raised at the beginning of a simulation step, before any collision detection, constraint solving, or integration is performed.
[CallbackThread(ThreadContext.MainThread)]
public event World.WorldStep? PreStep
Event Type
Remarks
This event is invoked once per call to Step(float, bool) and receives the full
step time dt. It can be used to apply external forces, modify bodies,
or gather per-step diagnostics before the simulation advances.
PreSubStep
Raised at the beginning of each substep during a simulation step.
[CallbackThread(ThreadContext.MainThread)]
public event World.WorldStep? PreSubStep
Event Type
Remarks
A simulation step may be divided into multiple substeps for stability.
This event is invoked once per substep and receives the substep duration
(dt / substepCount). It is called immediately before force integration
and constraint solving for the substep.