Table of Contents

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

bool

BroadPhaseFilter

Hook into the broadphase collision detection pipeline. The default value is null.

public IBroadPhaseFilter? BroadPhaseFilter { get; set; }

Property Value

IBroadPhaseFilter

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

ReadOnlySpan<double>

DynamicTree

Access to the DynamicTree instance. The instance should only be modified by Jitter.

public DynamicTree DynamicTree { get; }

Property Value

DynamicTree

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

bool

Gravity

Default gravity, see also AffectedByGravity. Default value: (0, -9.81, 0).

public JVector Gravity { get; set; }

Property Value

JVector

Islands

All collision islands in this world.

public ReadOnlyPartitionedSet<Island> Islands { get; }

Property Value

ReadOnlyPartitionedSet<Island>

NarrowPhaseFilter

Hook into the narrow-phase collision detection pipeline. The default instance is of type TriangleEdgeCollisionFilter.

public INarrowPhaseFilter? NarrowPhaseFilter { get; set; }

Property Value

INarrowPhaseFilter

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

RigidBody

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

World.SpanData

RigidBodies

All rigid bodies in this world.

public ReadOnlyPartitionedSet<RigidBody> RigidBodies { get; }

Property Value

ReadOnlyPartitionedSet<RigidBody>

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 solver is less than 1 or relaxation is 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

float

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

float

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

int

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

World.ThreadModelType

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

body1 RigidBody

The first rigid body involved in the constraint.

body2 RigidBody

The second rigid body involved in the constraint.

Returns

T

A new instance of the specified constraint type, already registered with the world.

Type Parameters

T

The specific type of constraint to create.

Exceptions

ArgumentException

Thrown if body1 and body2 are 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

RigidBody

A newly created instance of RigidBody.

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

proxyA IDynamicTreeProxy
proxyB IDynamicTreeProxy

Returns

bool

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

id0 ulong

The first identifier (e.g., shape ID).

id1 ulong

The second identifier.

arbiter Arbiter

When this method returns true, contains the arbiter; otherwise, null.

Returns

bool

true if an arbiter exists for the ordered ID pair; otherwise, false.

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

id0 ulong

The first identifier associated with the contact (e.g., shape or feature ID).

id1 ulong

The second identifier associated with the contact.

body1 RigidBody

The first rigid body. Used only if a new arbiter is created.

body2 RigidBody

The second rigid body. Used only if a new arbiter is created.

arbiter Arbiter

The 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

b1 RigidBodyData

Reference to the first rigid body data.

b2 RigidBodyData

Reference 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

arbiter Arbiter

The existing Arbiter instance to which the contact will be added.

point1 JVector

The contact point on the first body, in world space.

point2 JVector

The contact point on the second body, in world space.

normal JVector

The contact normal, in world space. Must be normalized.

removeFlags ContactData.SolveMode

A 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

id0 ulong

The first identifier associated with the contact (e.g., shape or feature ID).

id1 ulong

The second identifier associated with the contact.

body1 RigidBody

The first rigid body involved in the contact.

body2 RigidBody

The second rigid body involved in the contact.

normal JVector

The contact normal, in world space. Must be a unit vector pointing from body1 toward body2.

manifold CollisionManifold

A CollisionManifold containing contact point pairs in world space.

removeFlags ContactData.SolveMode

A 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

id0 ulong

The first identifier associated with the contact (e.g., shape or feature ID).

id1 ulong

The second identifier associated with the contact.

body1 RigidBody

The first rigid body involved in the contact.

body2 RigidBody

The second rigid body involved in the contact.

point1 JVector

The contact point on body1, in world space.

point2 JVector

The contact point on body2, in world space.

normal JVector

The contact normal, in world space. Must be a unit vector pointing from body1 toward body2.

removeFlags ContactData.SolveMode

A 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

arbiter Arbiter

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

constraint Constraint

The 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

body RigidBody

The 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

count int

The 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

dt float

The reference timestep in seconds used to scale bias and softness terms.

solverIterations int

The number of solver iterations to execute.

relaxationIterations int

The number of relaxation iterations to execute after solving.

multiThread bool

If 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 dt is negative, solverIterations is less than 1, or relaxationIterations is negative.

Step(float, bool)

Performs a single simulation step.

public void Step(float dt, bool multiThread = true)

Parameters

dt float

The duration of time to simulate in seconds. Should remain fixed and typically not exceed 1/60 s.

multiThread bool

If 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 dt is 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

b1 RigidBodyData

Reference to the first rigid body data.

b2 RigidBodyData

Reference to the second rigid body data.

Returns

bool

true if both locks were acquired; otherwise, false.

UnlockTwoBody(ref RigidBodyData, ref RigidBodyData)

public static void UnlockTwoBody(ref RigidBodyData b1, ref RigidBodyData b2)

Parameters

b1 RigidBodyData

Reference to the first rigid body data.

b2 RigidBodyData

Reference 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

World.WorldStep

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

World.WorldStep

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

World.WorldStep

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

World.WorldStep

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.