Generated from the public headers, which are the source of truth: 306 functions across 11 headers.
base.hThe base of the Maul3D API: the library version, the export and attribute macros, the result codes every fallible function returns, the allocator, the ids every header shares, and hashing.
m3Version m3GetVersion(void);
Returns the version of the library that was linked, which may differ from the M3_VERSION macros a program was compiled with.
Returns: The library version.
Thread safety. Safe from any thread.
const char* m3GetResultName(m3Result result);
Returns the name of a result code, for diagnostics.
Parameters:
result: Any value; an unknown one is named as such.Returns: A static, NUL-terminated string such as "m3_errorCapacity".
Thread safety. Safe from any thread.
const char* m3GetSimdBackend(void);
Returns the SIMD backend the library was compiled for: "avx2", "neon" or "scalar". Every backend produces the same bits; this only reports which kernels the binary carries.
Returns: A static, NUL-terminated string.
Thread safety. Safe from any thread.
bool m3IsCpuBackendSupported(void);
Returns whether the CPU running the call supports the compiled backend. An "avx2" binary needs AVX2 and FMA3 with the wide registers enabled by the operating system; "neon" and "scalar" run on every CPU of their architecture. m3CreateWorld refuses a CPU without the backend with m3_errorUnsupported, so a program can call this first to choose another path, or build with -DMAUL3D_SIMD=scalar.
Returns: Whether the CPU can run this library.
Thread safety. Safe from any thread.
uint64_t m3Hash64(uint64_t seed, const void* data, int64_t byteCount);
The 64-bit hash every determinism check is built on: eight bytes a round, xored in, multiplied by an odd constant and folded, the leftover bytes one at a time (FNV-1a). Its constants are frozen.
Parameters:
seed: The running hash; start a chain with M3_HASH_INIT.data: The bytes to fold in; may be null when byteCount is 0.byteCount: The number of bytes, at least 0.Returns: The new running hash.
Thread safety. Safe from any thread.
body.hRigid bodies: creation and destruction, motion, forces and impulses, mass, sleep, and state readback.
m3BodyDef m3DefaultBodyDef(void);
Returns a def with pinned defaults (identity rotation, gravity scale one, sleep and simulation enabled) and a valid cookie.
Returns: A static body def at the origin, with the cookie m3CreateBody checks.
Thread safety. Safe from any thread.
M3_NODISCARD M3_API m3Result m3CreateBody(m3World* world, const m3BodyDef* def, m3BodyId* bodyOut);
Create a body. Returns m3_errorInvalid for an invalid def, m3_errorLimit for a position, velocity, spin or gravity scale past its bound in maul3d/base.h, and m3_errorCapacity for an exhausted body pool; *bodyOut is the null id on any failure. A shapeless dynamic body has unit mass and zero inertia until a shape provides the real values. Journaled.
Parameters:
world: The world.def: The def, from m3DefaultBodyDef.bodyOut: Receives the new id; any failure leaves the null id there when it is not null.Returns: m3_success; m3_errorInvalid for a null world, def or bodyOut, a def m3DefaultBodyDef did not make, a type out of range, a rotation that is not finite or not near unit, a damping that is not finite or is negative, a sleep threshold that is not finite or is negative, a static def whose velocity or spin is not zero, infinities included, or a NaN position, velocity, spin or gravity scale; m3_errorLimit for a position, velocity, spin or gravity scale past its bound, infinities included; m3_errorCapacity for a full body pool; m3_errorBusy from host code the world is running. Every refusal but a full pool's and a null world's counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3DestroyBody(m3World* world, m3BodyId body);
Destroy a body. The id goes stale; the slot recycles FIFO with a generation bump and retires after 2^32 objects instead of wrapping. A stale id returns m3_errorStale and the null id m3_errorInvalid; every destroy of an object a world owns answers the same way. The body's shapes and joints go with it, and a vehicle whose chassis it is. Journaled.
Parameters:
world: The world.body: The body.Returns: m3_success; m3_errorInvalid for a null world, the null id or a character's body; m3_errorStale for a gone body; m3_errorBusy from host code the world is running. Each refusal but a null world's counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time.
bool m3Body_IsValid(const m3World* world, m3BodyId body);
Returns whether the id names a live body of this world.
Parameters:
world: The world; null gives false.body: The id.Returns: Whether the body is alive.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
m3Pos3 m3Body_GetPosition(const m3World* world, m3BodyId body);
Returns the body origin's world position.
Parameters:
world: The world.body: The body.Returns: The position; the origin for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
m3Quat m3Body_GetRotation(const m3World* world, m3BodyId body);
Returns the body's rotation.
Parameters:
world: The world.body: The body.Returns: The rotation; identity for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
m3Vec3 m3Body_GetLinearVelocity(const m3World* world, m3BodyId body);
Returns the velocity of the body's center of mass, m/s.
Parameters:
world: The world.body: The body.Returns: The velocity; zero for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
m3Vec3 m3Body_GetAngularVelocity(const m3World* world, m3BodyId body);
Returns the body's angular velocity in the world frame, rad/s.
Parameters:
world: The world.body: The body.Returns: The angular velocity; zero for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
uint64_t m3Body_GetUserData(const m3World* world, m3BodyId body);
Returns the host's value the def or m3Body_SetUserData set.
Parameters:
world: The world.body: The body.Returns: The value; 0 for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
m3BodyType m3Body_GetType(const m3World* world, m3BodyId body);
Returns the body's type.
Parameters:
world: The world.body: The body.Returns: The type; m3_staticBody for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
m3Transform m3Body_GetTransform(const m3World* world, m3BodyId body);
Returns the body's position and rotation together.
Parameters:
world: The world.body: The body.Returns: The transform; identity at the origin for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
float m3Body_GetMass(const m3World* world, m3BodyId body);
Returns the body's mass in kilograms.
Parameters:
world: The world.body: The body.Returns: The mass; 0 for a static or kinematic body, for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
m3Mat3 m3Body_GetCentralInertia(const m3World* world, m3BodyId body);
Returns the inertia tensor about the center of mass, in the body frame, kg m^2.
Parameters:
world: The world.body: The body.Returns: The tensor; zero for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
m3Vec3 m3Body_GetLocalCenter(const m3World* world, m3BodyId body);
Returns the center of mass in the body frame.
Parameters:
world: The world.body: The body.Returns: The center; zero for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
m3Pos3 m3Body_GetWorldCenterOfMass(const m3World* world, m3BodyId body);
Returns the center of mass in world space.
Parameters:
world: The world.body: The body.Returns: The center; the origin for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
m3Pos3 m3Body_GetWorldPoint(const m3World* world, m3BodyId body, m3Vec3 localPoint);
Converts a point from the body frame to world space.
Parameters:
world: The world.body: The body.localPoint: The point in the body frame.Returns: The world point; the origin for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
m3Vec3 m3Body_GetLocalPoint(const m3World* world, m3BodyId body, m3Pos3 worldPoint);
Converts a world point to the body frame.
Parameters:
world: The world.body: The body.worldPoint: The point in world space.Returns: The body-frame point; zero for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
m3Vec3 m3Body_GetWorldVector(const m3World* world, m3BodyId body, m3Vec3 localVector);
Rotates a vector from the body frame to world space.
Parameters:
world: The world.body: The body.localVector: The vector in the body frame.Returns: The world vector; zero for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
m3Vec3 m3Body_GetLocalVector(const m3World* world, m3BodyId body, m3Vec3 worldVector);
Rotates a world vector into the body frame.
Parameters:
world: The world.body: The body.worldVector: The vector in world space.Returns: The body-frame vector; zero for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
m3Vec3 m3Body_GetWorldPointVelocity(const m3World* world, m3BodyId body, m3Pos3 worldPoint);
Returns the velocity of the body's material at a world point.
Parameters:
world: The world.body: The body.worldPoint: The point in world space.Returns: The velocity, m/s; zero for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
m3Vec3 m3Body_GetLocalPointVelocity(const m3World* world, m3BodyId body, m3Vec3 localPoint);
Returns the velocity of the body's material at a body-frame point.
Parameters:
world: The world.body: The body.localPoint: The point in the body frame.Returns: The velocity, m/s; zero for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
float m3Body_GetGravityScale(const m3World* world, m3BodyId body);
Returns the body's gravity scale.
Parameters:
world: The world.body: The body.Returns: The scale; 0 for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
float m3Body_GetLinearDamping(const m3World* world, m3BodyId body);
Returns the body's linear damping.
Parameters:
world: The world.body: The body.Returns: The damping; 0 for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
float m3Body_GetAngularDamping(const m3World* world, m3BodyId body);
Returns the body's angular damping.
Parameters:
world: The world.body: The body.Returns: The damping; 0 for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
bool m3Body_IsBulletEnabled(const m3World* world, m3BodyId body);
Returns whether the body is a bullet.
Parameters:
world: The world.body: The body.Returns: Whether it is; false for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3Body_SetGravityScale(m3World* world, m3BodyId body, float scale);
Sets the body's gravity scale. Journaled. A stale or null id, a refused value, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.body: The body.scale: The scale, finite and within 1e4.Thread safety. Safe from any thread; a world is used by one thread at a time.
void m3Body_SetLinearDamping(m3World* world, m3BodyId body, float damping);
Sets the body's linear damping. Journaled. A stale or null id, a refused value, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.body: The body.damping: The damping, finite and not negative.Thread safety. Safe from any thread; a world is used by one thread at a time.
void m3Body_SetAngularDamping(m3World* world, m3BodyId body, float damping);
Sets the body's angular damping. Journaled. A stale or null id, a refused value, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.body: The body.damping: The damping, finite and not negative.Thread safety. Safe from any thread; a world is used by one thread at a time.
void m3Body_EnableBullet(m3World* world, m3BodyId body, bool flag);
Turns the bullet flag on or off; see m3BodyDef.enableBullet. Journaled. A stale or null id, a refused value, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.body: The body.flag: Whether the body is a bullet.Thread safety. Safe from any thread; a world is used by one thread at a time.
void m3Body_SetUserData(m3World* world, m3BodyId body, uint64_t userData);
Sets the host's value, carried unchanged. Journaled. A stale or null id, a refused value, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.body: The body.userData: The value.Thread safety. Safe from any thread; a world is used by one thread at a time.
m3WorldAabb m3Body_ComputeAabb(const m3World* world, m3BodyId body);
Returns the union of the shapes' broadphase bounds, margin included, or the body origin for a shapeless body.
Parameters:
world: The world.body: The body.Returns: The bounds; a box at the origin for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
int32_t m3Body_GetShapes(const m3World* world, m3BodyId body, m3ShapeId* idsOut, int32_t capacity);
The body's shapes or joints, up to capacity ids; returns the total, which may exceed capacity, and a NULL array with capacity 0 measures. A stale body is a refusal. A refusal zeroes the array over its whole capacity; a success, an empty one included, writes only its entries; a list call only reads, so none is refused as busy.
Parameters:
world: The world.body: The body.idsOut: Receives up to capacity shape ids, in ascending slot order.capacity: idsOut's length, at least 0.Returns: The total number of the body's shapes; 0 on a refusal: a null world, a stale or null id, a negative capacity or a null idsOut with a positive one, each counting one misuse but a null world's.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
int32_t m3Body_GetJoints(const m3World* world, m3BodyId body, m3JointId* idsOut, int32_t capacity);
The body's joints, as m3Body_GetShapes lists its shapes.
Parameters:
world: The world.body: The body.idsOut: Receives up to capacity joint ids, in ascending slot order.capacity: idsOut's length, at least 0.Returns: The total number of the body's joints; 0 on a refusal, as m3Body_GetShapes.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3Body_SetTransform(m3World* world, m3BodyId body, m3Pos3 position, m3Quat rotation);
Journaled setters: every mutation is a discrete op. Runtime control, all journaled. SetTransform is the teleport: the pose lands instantly, velocities stay, and bodies around BOTH the old and new locations wake so nothing keeps sleeping under or inside a teleported crate. The position must lie within 1e15 m of the origin on every axis. A stale or null id, a refused value, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.body: The body.position: The new origin, within 1e15 m on every axis.rotation: The new rotation, a unit quaternion.Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3Body_SetTargetTransform(m3World* world, m3BodyId body, m3Pos3 position, m3Quat rotation);
Kinematic servo: velocities are chosen at the next step so the body lands ON the target pose after that step, then the target clears. Kinematic bodies only (the correct way to drive elevators and doors). Journaled. Returns m3_success; m3_errorLimit for a target more than M3_TARGET_REACH_LIMIT from where the body is, which the step decides, so it changes nothing and counts no misuse; m3_errorStale for a stale id, m3_errorInvalid for the null id, a body that is not kinematic or a pose that is not finite, normalized and within 1e15 m, and m3_errorBusy inside a step callback, which change nothing and count one misuse.
Parameters:
world: The world.body: The body.position: The target origin.rotation: The target rotation, a unit quaternion.Returns: m3_success, or one of the refusals above.
Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3Body_SetType(m3World* world, m3BodyId body, m3BodyType type);
Switch dynamic, kinematic, static at runtime. Mass rebuilds from shapes when turning dynamic; velocities zero when turning static; a pending force and torque drop when turning static or kinematic; the neighborhood wakes. Journaled. Returns m3_success; m3_errorLimit when a joint on the body would pass its lever ratio at the new type's mass, when the body would turn dynamic with a shape below the mass floors or a total mass past M3_MASS_LIMIT, or when its linear velocity is past the new type's limit, which change nothing and count no misuse; m3_errorStale for a stale id, m3_errorInvalid for the null id, a type out of range, a character's body, or a body holding a plane, mesh, height field or voxel chunk that would leave static, and m3_errorBusy inside a step callback, which change nothing and count one misuse.
Parameters:
world: The world.body: The body.type: The new type.Returns: m3_success, or one of the refusals above.
Thread safety. Safe from any thread; a world is used by one thread at a time.
void m3Body_Enable(m3World* world, m3BodyId body, bool enable);
A disabled body vanishes from simulation AND queries without being destroyed, and drops a pending force and torque; enabling wakes its neighborhood. Journaled. A stale or null id, a refused value, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.body: The body.enable: Whether the body takes part.Thread safety. Safe from any thread; a world is used by one thread at a time.
bool m3Body_IsEnabled(const m3World* world, m3BodyId body);
Returns whether the body takes part in simulation and queries.
Parameters:
world: The world.body: The body.Returns: Whether it does; false for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3Body_SetMotionLocks(m3World* world, m3BodyId body, m3MotionLocks locks);
Motion locks: locked components re-zero every substep, so 2.5D scenes and upright enemies stay exact. Journaled. A stale or null id, a refused value, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.body: The body.locks: The axes to hold still.Thread safety. Safe from any thread; a world is used by one thread at a time.
m3MotionLocks m3Body_GetMotionLocks(const m3World* world, m3BodyId body);
Returns the body's motion locks.
Parameters:
world: The world.body: The body.Returns: The locks; none for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3Body_EnableFastRotation(m3World* world, m3BodyId body, bool flag);
Let this body spin past the world's angular speed cap (for wheels and other legal fast spinners), up to the 1e5 rad/s the step holds every body within. Journaled. A stale or null id, a refused value, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.body: The body.flag: Whether the body may spin past the world's cap.Thread safety. Safe from any thread; a world is used by one thread at a time.
bool m3Body_IsFastRotationEnabled(const m3World* world, m3BodyId body);
Returns whether the body may spin past the world's angular cap.
Parameters:
world: The world.body: The body.Returns: Whether it may; false for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
M3_NODISCARD M3_API m3Result m3Body_SetName(m3World* world, m3BodyId body, const char* name, int32_t byteCount);
A body's debug name: UTF-8 of at most M3_MAX_BODY_NAME_BYTES bytes, with no zero byte. Journaled and carried by snapshots, never part of the hash (a label moves no matter). A body starts unnamed, and a byteCount of 0 clears the name. name may be NULL when byteCount is 0. Returns m3_success; m3_errorLimit for a byteCount past M3_MAX_BODY_NAME_BYTES; m3_errorStale for a stale id; m3_errorInvalid for a NULL world, the null id, a negative byteCount, a NULL name with a positive byteCount, or bytes that are not valid UTF-8 or hold a zero byte; m3_errorBusy inside a step callback. Every refusal changes nothing and counts one misuse.
Parameters:
world: The world.body: The body.name: The name's bytes, no terminator needed.byteCount: The name's length in bytes, 0 to M3_MAX_BODY_NAME_BYTES.Returns: m3_success, or one of the refusals above.
Thread safety. Safe from any thread; a world is used by one thread at a time.
int32_t m3Body_GetName(const m3World* world, m3BodyId body, char* nameOut, int32_t capacity);
Copies a body's name into nameOut, with no terminator, and returns its byte length, 0 for an unnamed body. The name is written only when it fits whole: a capacity below its length zeroes nameOut over its capacity and still returns the length, so a NULL nameOut with capacity 0 measures, and a capacity of M3_MAX_BODY_NAME_BYTES always fits. A stale id, a NULL world, a negative capacity or a NULL nameOut with a positive capacity returns 0 and counts one misuse; nameOut is then zeroed over its capacity whenever it and the capacity are valid.
Parameters:
world: The world.body: The body.nameOut: Receives the name's bytes, with no terminator.capacity: nameOut's length in bytes, at least 0.Returns: The name's length in bytes, or 0 on a refusal.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
int32_t m3Body_GetContactData(const m3World* world, m3BodyId body, m3ContactData* dataOut, int32_t capacity);
Who touches me now: fills up to capacity entries and returns the total, which may exceed capacity; a NULL array with capacity 0 measures. A stale body is a refusal. A refusal zeroes the array over its whole capacity; a success, an empty one included, writes only its entries; a list call only reads, so none is refused as busy. See m3ContactData in world.h.
Parameters:
world: The world.body: The body.dataOut: Receives up to capacity contacts.capacity: dataOut's length, at least 0.Returns: The total number of the body's touching contacts; 0 on a refusal.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3Body_EnableSleep(m3World* world, m3BodyId body, bool flag);
Whether this body may fall asleep; turning it off wakes it. Journaled. A stale or null id, a refused value, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.body: The body.flag: Whether the body may sleep.Thread safety. Safe from any thread; a world is used by one thread at a time.
bool m3Body_IsSleepEnabled(const m3World* world, m3BodyId body);
Returns whether the body may fall asleep.
Parameters:
world: The world.body: The body.Returns: Whether it may; false for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3Body_SetSleepThreshold(m3World* world, m3BodyId body, float threshold);
The speed below which this body counts as resting; zero restores the world default. Journaled. A stale or null id, a refused value, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.body: The body.threshold: The resting speed, m/s, finite and not negative; 0 restores the world default.Thread safety. Safe from any thread; a world is used by one thread at a time.
float m3Body_GetSleepThreshold(const m3World* world, m3BodyId body);
Returns the speed below which the body counts as resting.
Parameters:
world: The world.body: The body.Returns: The threshold, m/s; 0 for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
bool m3Body_IsAwake(const m3World* world, m3BodyId body);
Returns whether the body is awake.
Parameters:
world: The world.body: The body.Returns: Whether it is; false for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3Body_SetAwake(m3World* world, m3BodyId body, bool awake);
SetAwake(true) wakes; SetAwake(false) puts the single body to sleep, zeroes its velocities and drops a pending force and torque. Journaled. Only a dynamic body takes it: another type is refused. A stale or null id, a refused value, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.body: The body.awake: Whether the body is awake.Thread safety. Safe from any thread; a world is used by one thread at a time.
void m3Body_ApplyForce(m3World* world, m3BodyId body, m3Vec3 force);
Adds a force at the center of mass for the next step. Journaled. Only an enabled dynamic body takes it: a static, kinematic or disabled target is refused. The force and torque the body holds for the step stay within 1e20 on every axis: a call that would pass that, or a force that is not finite, is refused whole. A stale or null id, a refused target, value or point, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.body: The body.force: The force, newtons.Thread safety. Safe from any thread; a world is used by one thread at a time.
void m3Body_ApplyTorque(m3World* world, m3BodyId body, m3Vec3 torque);
Adds a torque for the next step. Journaled. Only an enabled dynamic body takes it: a static, kinematic or disabled target is refused. The torque the body holds for the step stays within 1e20 on every axis: a call that would pass that, or a torque that is not finite, is refused whole. A stale or null id, a refused target, value or point, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.body: The body.torque: The torque, N m, in the world frame.Thread safety. Safe from any thread; a world is used by one thread at a time.
void m3Body_ApplyLinearImpulse(m3World* world, m3BodyId body, m3Vec3 impulse);
Changes the velocity at once by impulse over mass. Journaled. Only a dynamic body takes it: a static or kinematic target is refused. The impulse may leave the body at most 1e5 m/s and rad/s on every axis: a call that would pass that, or an impulse that is not finite, is refused whole. A stale or null id, a refused target, value or point, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.body: The body.impulse: The impulse, N s, at the center of mass.Thread safety. Safe from any thread; a world is used by one thread at a time.
void m3Body_ApplyAngularImpulse(m3World* world, m3BodyId body, m3Vec3 impulse);
Changes the angular velocity at once. Journaled. Only a dynamic body takes it: a static or kinematic target is refused. The impulse may leave the body at most 1e5 m/s and rad/s on every axis: a call that would pass that, or an impulse that is not finite, is refused whole. A stale or null id, a refused target, value or point, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.body: The body.impulse: The angular impulse, N m s, in the world frame.Thread safety. Safe from any thread; a world is used by one thread at a time.
void m3Body_ApplyForceAtPoint(m3World* world, m3BodyId body, m3Vec3 force, m3Pos3 point);
Adds a force at a world point for the next step, with the torque its arm gives. Journaled. Only an enabled dynamic body takes it: a static, kinematic or disabled target is refused. The force and torque the body holds for the step stay within 1e20 on every axis: a call that would pass that, or a force that is not finite, is refused whole. A point that is not finite is refused. A stale or null id, a refused target, value or point, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.body: The body.force: The force, newtons.point: Where it acts, in world space.Thread safety. Safe from any thread; a world is used by one thread at a time.
void m3Body_ApplyLinearImpulseAtPoint(m3World* world, m3BodyId body, m3Vec3 impulse, m3Pos3 point);
Applies an impulse at a world point, changing both velocities at once. Journaled. Only a dynamic body takes it: a static or kinematic target is refused. The impulse may leave the body at most 1e5 m/s and rad/s on every axis: a call that would pass that, or an impulse that is not finite, is refused whole. A point that is not finite is refused. A stale or null id, a refused target, value or point, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.body: The body.impulse: The impulse, N s.point: Where it acts, in world space.Thread safety. Safe from any thread; a world is used by one thread at a time.
void m3Body_SetLinearVelocity(m3World* world, m3BodyId body, m3Vec3 velocity);
Velocities, journaled: within 1e5 m/s on every axis (1e10 m/s for a kinematic body), and every body's spin within 1e5 rad/s. Setting a velocity wakes the body. A static body never moves, so it takes no velocity: the call is refused. A stale or null id, a static body, a refused value, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.body: The body.velocity: The velocity of the center of mass, m/s.Thread safety. Safe from any thread; a world is used by one thread at a time.
void m3Body_SetAngularVelocity(m3World* world, m3BodyId body, m3Vec3 velocity);
Sets the angular velocity in the world frame, within 1e5 rad/s on every axis, and wakes the body. A static body is refused. A stale or null id, a static body, a refused value, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.body: The body.velocity: The angular velocity, rad/s.Thread safety. Safe from any thread; a world is used by one thread at a time.
character.hThe character controller: a kinematic capsule moved by collide-and-slide over the engine's convex casts. Its body never moves during m3World_Step; every displacement comes from m3Character_Move, a journaled command that rollback covers. Gravity is the host's job: add it to each move.
m3CharacterDef m3DefaultCharacterDef(void);
Returns a character def with the defaults: a 0.4 m radius, a 0.5 m half height, a 0.8 rad slope limit, a 0.3 m snap, a 0.02 m skin, a 0.35 m step, 80 kg and a push ratio of 2, at the origin.
Returns: The def, with the cookie m3CreateCharacter checks.
Thread safety. Safe from any thread.
M3_NODISCARD M3_API m3Result m3CreateCharacter(m3World* world, const m3CharacterDef* def, m3CharacterId* characterOut);
Creates the character and its internal kinematic capsule body (destroyed together). The body collides like any kinematic: dynamics bounce off it; it walks through nothing. The character owns the body and the capsule, which queries report like any shape: m3DestroyShape, m3DestroyBody, m3Body_SetType, m3Shape_SetSphere, m3Shape_SetCapsule and a shape create on that body refuse them with m3_errorInvalid. Destroy the character instead; m3Character_SetStance resizes it. A def value past the bound its field names returns m3_errorLimit, any other bad field m3_errorInvalid. Journaled.
Parameters:
world: The world.def: The def, from m3DefaultCharacterDef.characterOut: Receives the new id; any failure leaves the null id there when it is not null.Returns: m3_success; m3_errorInvalid for a null world, def or characterOut, a def m3DefaultCharacterDef did not make, a slope outside (0, 1.5] rad, a snap distance or step height that is negative or not finite, a skin that is not finite or not positive, a radius or mass that is not positive or is NaN, a half height or push ratio that is negative or NaN, or a NaN position; m3_errorLimit for a position past M3_POSITION_LIMIT, a radius or half height past M3_LOCAL_LIMIT, a mass outside M3_MIN_MASS to M3_MASS_LIMIT or a push ratio past M3_RATIO_LIMIT, infinities included; m3_errorCapacity when the world has no room for the character, its body or its capsule; m3_errorBusy from host code the world is running. Every refusal but a full world's and a null world's counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3DestroyCharacter(m3World* world, m3CharacterId character);
Destroys a character with its body and capsule. Journaled.
Parameters:
world: The world.character: The character.Returns: m3_success; m3_errorInvalid for a null world or the null id; m3_errorStale for an id whose character is gone; m3_errorBusy from host code the world is running. Each refusal but a null world's counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time.
bool m3Character_IsValid(const m3World* world, m3CharacterId character);
Returns whether the id names a live character of this world.
Parameters:
world: The world; null gives false.character: The id.Returns: Whether the character is alive.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3Character_Move(m3World* world, m3CharacterId character, m3Vec3 translation);
Collide-and-slide by translation, immediately: cast the capsule, advance to the first hit, slide the remainder along the surface, repeat (bounded), then snap to walkable ground within snapDistance when descending. Walkable is measured against maxSlopeAngle; ceilings and steep walls only ever block and slide. Journaled; a translation past 1e18 m on any axis, or not finite, is refused.
Parameters:
world: The world.character: The character; a stale or null id moves nothing and counts one misuse.translation: The wanted displacement, meters. A refused one changes nothing, is not journaled and counts one misuse, as does a call from host code the world is running.Thread safety. Safe from any thread; a world is used by one thread at a time.
m3Pos3 m3Character_GetPosition(const m3World* world, m3CharacterId character);
Returns the capsule's center.
Parameters:
world: The world.character: The character.Returns: The center; the origin for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
bool m3Character_IsGrounded(const m3World* world, m3CharacterId character);
Returns whether the character stands on walkable ground.
Parameters:
world: The world.character: The character.Returns: Whether it is grounded; false for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
m3Vec3 m3Character_GetGroundNormal(const m3World* world, m3CharacterId character);
The last walkable surface normal (zeros while airborne).
Parameters:
world: The world.character: The character.Returns: The normal; zeros while airborne, for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
m3BodyId m3Character_GetGroundBody(const m3World* world, m3CharacterId character);
The body under the character's feet (null while airborne or after that body is destroyed). Each m3World_Step carries grounded characters along with this body's motion through the regular slide casts: kinematic platforms, elevators, and dynamic fragments all ferry their riders.
Parameters:
world: The world.character: The character.Returns: The ground body's id; the null id while airborne, once that body is gone, for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
M3_NODISCARD M3_API m3Result m3Character_SetStance(m3World* world, m3CharacterId character, float halfHeight, float radius);
Stance: resize the capsule in place, FEET ANCHORED (the center moves so the capsule bottom stays level; a mid air crouch therefore lands shorter, not higher). Shrinking always applies. Growing runs the stand-up veto: the grown capsule is cast at its new pose through the same core every move uses, and ANY contact within the skin (a pressing ceiling, a wall against a wider radius) refuses the whole change with m3_errorState and counts no misuse; stance is untouched. A NaN dimension returns m3_errorInvalid, and one outside M3_MIN_STANCE to M3_STANCE_LIMIT m3_errorLimit, both counting one misuse; a stale id returns m3_errorStale. Journaled only when applied; the veto's refusal is bit-deterministic so twins and replays refuse together. Stance is state: snapshotted, hashed, rolled back like everything else.
Parameters:
world: The world.character: The character.halfHeight: The new segment half length, meters.radius: The new radius, meters.Returns: m3_success; m3_errorInvalid for a null world, the null id or a NaN dimension; m3_errorStale for a gone character; m3_errorLimit for a dimension outside M3_MIN_STANCE to M3_STANCE_LIMIT; m3_errorState when the stand-up veto refuses; m3_errorBusy from host code the world is running. Every refusal but the veto's and a null world's counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time.
void m3Character_GetStance(const m3World* world, m3CharacterId character, float* halfHeightOut, float* radiusOut);
Read the live stance (zeros on a stale id).
Parameters:
world: The world.character: The character; a stale or null id counts one misuse.halfHeightOut: Receives the segment half length, or 0 for a missing character; may be null.radiusOut: Receives the radius, or 0 for a missing character; may be null.Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
core_math.hDeterministic 3D math. World positions are 64-bit (m3Pos3) and everything local is a 32-bit float. Every operation is plain IEEE arithmetic under -ffp-contract=off, so the bits agree on every platform; the transcendentals are the engine's own.
static inline m3Vec3 m3MulMV3(m3Mat3 m, m3Vec3 v);
Column-major matrix times vector: cxv.x + cyv.y + cz*v.z.
static inline m3Vec3 m3Add3(m3Vec3 a, m3Vec3 b);
static inline m3Vec3 m3Sub3(m3Vec3 a, m3Vec3 b);
static inline m3Vec3 m3MulSV3(float s, m3Vec3 v);
static inline m3Vec3 m3Neg3(m3Vec3 v);
static inline float m3Dot3(m3Vec3 a, m3Vec3 b);
static inline m3Vec3 m3Cross3(m3Vec3 a, m3Vec3 b);
static inline float m3LengthSquared3(m3Vec3 v);
static inline float m3Length3(m3Vec3 v);
static inline m3Vec3 m3Normalize3(m3Vec3 v);
Normalize with a fixed degenerate fallback of {0, 1, 0}: one rule, documented, so a zero vector never turns into NaN and never depends on the caller.
static inline m3Quat m3MakeIdentityQuat(void);
static inline m3Quat m3MulQuat(m3Quat a, m3Quat b);
static inline m3Quat m3NormalizeQuat(m3Quat q);
Normalize with a fixed degenerate fallback of identity.
static inline m3Vec3 m3RotateVec3(m3Quat q, m3Vec3 v);
Rotate a vector by a unit quaternion: v' = v + w*t + q x t with t = 2 (q x v). Plain mul and add only, no fused ops.
static inline m3Vec3 m3InvRotateVec3(m3Quat q, m3Vec3 v);
Rotate by the conjugate (inverse for unit quaternions).
m3CosSin m3ComputeCosSin(float radians);
Deterministic cosine and sine: a quarter-turn reduction with a split pi/2, then Taylor series, hand rolled because platform libm implementations disagree in the last bits. Every build gives the same bits for the same angle.
Parameters:
radians: The angle, any finite value.Returns: The cosine and sine, scaled so cc + ss is one to float rounding.
Thread safety. Safe from any thread.
float m3Atan2(float y, float x);
Deterministic atan2: a pi/6 argument shift, then the Taylor series, hand rolled for the same reason as m3ComputeCosSin.
Parameters:
y: The sine side.x: The cosine side.Returns: The angle of (x, y) in radians, in [-pi, pi]; 0 for (0, 0).
Thread safety. Safe from any thread.
draw.hDebug draw: the world describes itself as segments, points and triangles through host callbacks. A draw pass only reads simulation state; a test hashes the world across a draw to check that.
void m3World_Draw(const m3World* world, const m3DebugDraw* draw);
Draws what the flags ask for through the callbacks given; a missing callback skips what it would draw. Solid shapes come first, then wireframes, bounds, contacts, joints and the rest. Reads simulation state only. The callbacks are host code the world runs: they may read the world, and a call that would change it is refused as busy.
Parameters:
world: The world; null draws nothing.draw: The callbacks and flags; null draws nothing and counts one misuse on the world.Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
joint.hJoints: the twelve joint types, their defs, limits, motors, springs, reaction force readback and breaking.
m3SphericalJointDef m3DefaultSphericalJointDef(void);
Returns a spherical joint def with the defaults: zero anchors, unit z twist axes, and no spring, twist limit or cone, with the cookie m3CreateSphericalJoint checks.
Returns: The def.
Thread safety. Safe from any thread.
m3RevoluteJointDef m3DefaultRevoluteJointDef(void);
Returns a revolute joint def with the defaults: zero anchors, unit z hinge axes, and no spring, motor or limit, with the cookie m3CreateRevoluteJoint checks.
Returns: The def.
Thread safety. Safe from any thread.
m3PrismaticJointDef m3DefaultPrismaticJointDef(void);
Returns a prismatic joint def with the defaults: zero anchors, unit z slide axes, and no spring, motor or limit, with the cookie m3CreatePrismaticJoint checks.
Returns: The def.
Thread safety. Safe from any thread.
m3WeldJointDef m3DefaultWeldJointDef(void);
Returns a weld joint def with the defaults: zero anchors, with the cookie m3CreateWeldJoint checks.
Returns: The def.
Thread safety. Safe from any thread.
m3DistanceJointDef m3DefaultDistanceJointDef(void);
Returns a distance joint def with the defaults: zero anchors, a zero range and rest length, and no spring, with the cookie m3CreateDistanceJoint checks.
Returns: The def.
Thread safety. Safe from any thread.
m3GenericJointDef m3DefaultGenericJointDef(void);
Returns a generic joint def with the defaults: zero anchors, unit z axes, every axis locked with zero limits, and no motor axis (M3_GENERIC_NO_MOTOR), with the cookie m3CreateGenericJoint checks.
Returns: The def.
Thread safety. Safe from any thread.
m3WheelJointDef m3DefaultWheelJointDef(void);
Returns a wheel joint def with the defaults: zero anchors, a suspension pointing down -y, an axle along z, and no spring, motor or limit, with the cookie m3CreateWheelJoint checks.
Returns: The def.
Thread safety. Safe from any thread.
m3FilterJointDef m3DefaultFilterJointDef(void);
Returns a filter joint def with the defaults: no bodies, with the cookie m3CreateFilterJoint checks.
Returns: The def.
Thread safety. Safe from any thread.
m3ParallelJointDef m3DefaultParallelJointDef(void);
Returns a parallel joint def with the defaults: unit z axes, with the cookie m3CreateParallelJoint checks.
Returns: The def.
Thread safety. Safe from any thread.
m3MotorJointDef m3DefaultMotorJointDef(void);
Returns a motor joint def with the defaults: zero anchors, no force or torque budget, and no spring, with the cookie m3CreateMotorJoint checks.
Returns: The def.
Thread safety. Safe from any thread.
m3GearJointDef m3DefaultGearJointDef(void);
Returns a gear joint def with the defaults: unit z axes and a ratio of 1, with the cookie m3CreateGearJoint checks.
Returns: The def.
Thread safety. Safe from any thread.
m3PulleyJointDef m3DefaultPulleyJointDef(void);
Returns a pulley joint def with the defaults: zero anchors, ground anchors at the origin and a ratio of 1, with the cookie m3CreatePulleyJoint checks.
Returns: The def.
Thread safety. Safe from any thread.
M3_NODISCARD M3_API m3Result m3CreateSphericalJoint(m3World* world, const m3SphericalJointDef* def, m3JointId* jointOut);
Create a joint between two distinct bodies of the same world (at least one dynamic). Each call takes only its own type's def: a def with another type's cookie, or none, is m3_errorInvalid. Returns m3_errorInvalid for a bad def, m3_errorLimit for a value past a bound in maul3d/base.h or for a spherical, revolute, prismatic, weld, wheel or motor joint whose bodies' lever ratio would pass M3_JOINT_LEVER_LIMIT, m3_errorStale for a stale body and m3_errorCapacity for an exhausted pool; a refusal other than the lever ratio and the full pool counts one misuse, and *jointOut is the null id on any failure. Journaled; replay verifies the minted id. Destroying either body destroys the joint.
Parameters:
world: The world.def: The def, from m3DefaultSphericalJointDef.jointOut: Receives the new id; any failure leaves the null id there when it is not null.Returns: m3_success; m3_errorInvalid for a null world, def or jointOut, a def m3DefaultSphericalJointDef did not make, a null body id, the same body twice, two bodies of which neither is dynamic, a NaN anchor, an axis that is not finite, a limit bound that is not finite (checked with the limit off too) or bounds out of order with the limit on, a cone angle that is negative or not finite (checked with the cone off too), a spring hertz or damping ratio that is negative or NaN (checked with the spring off too), or a zero hertz with the spring on; m3_errorStale for a stale body; m3_errorLimit for an anchor past M3_LOCAL_LIMIT, a spring hertz past 1e5 or a damping ratio past 1e4, infinities included; m3_errorLimit, counting no misuse, when the bodies' lever ratio would pass M3_JOINT_LEVER_LIMIT; m3_errorCapacity for a full joint pool; m3_errorBusy from host code the world is running. Every refusal but a full pool's, the lever's and a null world's counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3CreateRevoluteJoint(m3World* world, const m3RevoluteJointDef* def, m3JointId* jointOut);
Creates a revolute joint; see m3CreateSphericalJoint for the rules every create shares.
Parameters:
world: The world.def: The def, from m3DefaultRevoluteJointDef.jointOut: Receives the new id; any failure leaves the null id there when it is not null.Returns: m3_success; m3_errorInvalid for a null world, def or jointOut, a def m3DefaultRevoluteJointDef did not make, a null body id, the same body twice, two bodies of which neither is dynamic, a NaN anchor, an axis that is zero or not finite, a limit bound that is not finite (checked with the limit off too) or bounds out of order with the limit on, a NaN motor speed or a motor effort that is negative or NaN (checked with the motor off too), a spring hertz or damping ratio that is negative or NaN (checked with the spring off too), or a zero hertz with the spring on; m3_errorStale for a stale body; m3_errorLimit for an anchor past M3_LOCAL_LIMIT, a motor speed past 1e5 or an effort past 1e20, a spring hertz past 1e5 or a damping ratio past 1e4, infinities included; m3_errorLimit, counting no misuse, when the bodies' lever ratio would pass M3_JOINT_LEVER_LIMIT; m3_errorCapacity for a full joint pool; m3_errorBusy from host code the world is running. Every refusal but a full pool's, the lever's and a null world's counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3CreatePrismaticJoint(m3World* world, const m3PrismaticJointDef* def, m3JointId* jointOut);
Creates a prismatic joint; see m3CreateSphericalJoint for the rules every create shares.
Parameters:
world: The world.def: The def, from m3DefaultPrismaticJointDef.jointOut: Receives the new id; any failure leaves the null id there when it is not null.Returns: m3_success; m3_errorInvalid for a null world, def or jointOut, a def m3DefaultPrismaticJointDef did not make, a null body id, the same body twice, two bodies of which neither is dynamic, a NaN anchor, an axis that is zero or not finite, a limit bound that is not finite (checked with the limit off too) or bounds out of order with the limit on, a NaN motor speed or a motor effort that is negative or NaN (checked with the motor off too), a spring hertz or damping ratio that is negative or NaN (checked with the spring off too), or a zero hertz with the spring on; m3_errorStale for a stale body; m3_errorLimit for an anchor past M3_LOCAL_LIMIT, a motor speed past 1e5 or an effort past 1e20, a spring hertz past 1e5 or a damping ratio past 1e4, infinities included; m3_errorLimit, counting no misuse, when the bodies' lever ratio would pass M3_JOINT_LEVER_LIMIT; m3_errorCapacity for a full joint pool; m3_errorBusy from host code the world is running. Every refusal but a full pool's, the lever's and a null world's counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3CreateWeldJoint(m3World* world, const m3WeldJointDef* def, m3JointId* jointOut);
Creates a weld joint; see m3CreateSphericalJoint for the rules every create shares.
Parameters:
world: The world.def: The def, from m3DefaultWeldJointDef.jointOut: Receives the new id; any failure leaves the null id there when it is not null.Returns: m3_success; m3_errorInvalid for a null world, def or jointOut, a def m3DefaultWeldJointDef did not make, a null body id, the same body twice, two bodies of which neither is dynamic, a NaN anchor; m3_errorStale for a stale body; m3_errorLimit for an anchor past M3_LOCAL_LIMIT, infinities included; m3_errorLimit, counting no misuse, when the bodies' lever ratio would pass M3_JOINT_LEVER_LIMIT; m3_errorCapacity for a full joint pool; m3_errorBusy from host code the world is running. Every refusal but a full pool's, the lever's and a null world's counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3CreateDistanceJoint(m3World* world, const m3DistanceJointDef* def, m3JointId* jointOut);
Creates a distance joint; see m3CreateSphericalJoint for the rules every create shares.
Parameters:
world: The world.def: The def, from m3DefaultDistanceJointDef.jointOut: Receives the new id; any failure leaves the null id there when it is not null.Returns: m3_success; m3_errorInvalid for a null world, def or jointOut, a def m3DefaultDistanceJointDef did not make, a null body id, the same body twice, two bodies of which neither is dynamic, a NaN anchor, a range bound that is not finite or is negative, a minLength above maxLength, a rest length that is not finite or is negative, a spring hertz or damping ratio that is negative or NaN (checked with the spring off too), or a zero hertz with the spring on; m3_errorStale for a stale body; m3_errorLimit for an anchor past M3_LOCAL_LIMIT, a spring hertz past 1e5 or a damping ratio past 1e4, infinities included; m3_errorCapacity for a full joint pool; m3_errorBusy from host code the world is running. Every refusal but a full pool's and a null world's counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3CreateGenericJoint(m3World* world, const m3GenericJointDef* def, m3JointId* jointOut);
Creates a generic joint; see m3CreateSphericalJoint for the rules every create shares.
Parameters:
world: The world.def: The def, from m3DefaultGenericJointDef.jointOut: Receives the new id; any failure leaves the null id there when it is not null.Returns: m3_success; m3_errorInvalid for a null world, def or jointOut, a def m3DefaultGenericJointDef did not make, a null body id, the same body twice, two bodies of which neither is dynamic, a NaN anchor, an axis that is zero or not finite, an axis mode out of range, a limit bound that is not finite, a limited axis whose bounds are out of order, more than one limited angular axis or one whose other two are not both locked or both free, a motor axis past 5 that is not M3_GENERIC_NO_MOTOR, a motor on a locked axis, a NaN motor speed or a motor effort that is negative or NaN (checked with the motor off too); m3_errorStale for a stale body; m3_errorLimit for an anchor past M3_LOCAL_LIMIT, a motor speed past 1e5 or an effort past 1e20, infinities included; m3_errorCapacity for a full joint pool; m3_errorBusy from host code the world is running. Every refusal but a full pool's and a null world's counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3CreateWheelJoint(m3World* world, const m3WheelJointDef* def, m3JointId* jointOut);
Creates a wheel joint; see m3CreateSphericalJoint for the rules every create shares.
Parameters:
world: The world.def: The def, from m3DefaultWheelJointDef.jointOut: Receives the new id; any failure leaves the null id there when it is not null.Returns: m3_success; m3_errorInvalid for a null world, def or jointOut, a def m3DefaultWheelJointDef did not make, a null body id, the same body twice, two bodies of which neither is dynamic, a NaN anchor, an axis that is zero or not finite, an axle more than a small skew (|dot| > 0.1) off perpendicular to the suspension, a limit bound that is not finite (checked with the limit off too) or bounds out of order with the limit on, a NaN motor speed or a motor effort that is negative or NaN (checked with the motor off too), a spring hertz or damping ratio that is negative or NaN (checked with the spring off too), or a zero hertz with the spring on; m3_errorStale for a stale body; m3_errorLimit for an anchor past M3_LOCAL_LIMIT, a motor speed past 1e5 or an effort past 1e20, a spring hertz past 1e5 or a damping ratio past 1e4, infinities included; m3_errorLimit, counting no misuse, when the bodies' lever ratio would pass M3_JOINT_LEVER_LIMIT; m3_errorCapacity for a full joint pool; m3_errorBusy from host code the world is running. Every refusal but a full pool's, the lever's and a null world's counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3CreateFilterJoint(m3World* world, const m3FilterJointDef* def, m3JointId* jointOut);
Creates a filter joint; see m3CreateSphericalJoint for the rules every create shares.
Parameters:
world: The world.def: The def, from m3DefaultFilterJointDef.jointOut: Receives the new id; any failure leaves the null id there when it is not null.Returns: m3_success; m3_errorInvalid for a null world, def or jointOut, a def m3DefaultFilterJointDef did not make, a null body id, the same body twice, or two bodies of which neither is dynamic; m3_errorStale for a stale body; m3_errorCapacity for a full joint pool; m3_errorBusy from host code the world is running. Every refusal but a full pool's and a null world's counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3CreateParallelJoint(m3World* world, const m3ParallelJointDef* def, m3JointId* jointOut);
Creates a parallel joint; see m3CreateSphericalJoint for the rules every create shares.
Parameters:
world: The world.def: The def, from m3DefaultParallelJointDef.jointOut: Receives the new id; any failure leaves the null id there when it is not null.Returns: m3_success; m3_errorInvalid for a null world, def or jointOut, a def m3DefaultParallelJointDef did not make, a null body id, the same body twice, two bodies of which neither is dynamic, a NaN anchor, an axis that is zero or not finite; m3_errorStale for a stale body; m3_errorLimit for an anchor past M3_LOCAL_LIMIT, infinities included; m3_errorCapacity for a full joint pool; m3_errorBusy from host code the world is running. Every refusal but a full pool's and a null world's counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3CreateMotorJoint(m3World* world, const m3MotorJointDef* def, m3JointId* jointOut);
Creates a motor joint; see m3CreateSphericalJoint for the rules every create shares.
Parameters:
world: The world.def: The def, from m3DefaultMotorJointDef.jointOut: Receives the new id; any failure leaves the null id there when it is not null.Returns: m3_success; m3_errorInvalid for a null world, def or jointOut, a def m3DefaultMotorJointDef did not make, a null body id, the same body twice, two bodies of which neither is dynamic, a NaN anchor, a force or torque budget that is negative or NaN, a spring hertz or damping ratio that is negative or NaN (checked with the spring off too), or a zero hertz with the spring on; m3_errorStale for a stale body; m3_errorLimit for an anchor past M3_LOCAL_LIMIT, a budget past 1e20, a spring hertz past 1e5 or a damping ratio past 1e4, infinities included; m3_errorLimit, counting no misuse, when the bodies' lever ratio would pass M3_JOINT_LEVER_LIMIT; m3_errorCapacity for a full joint pool; m3_errorBusy from host code the world is running. Every refusal but a full pool's, the lever's and a null world's counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3CreateGearJoint(m3World* world, const m3GearJointDef* def, m3JointId* jointOut);
Creates a gear joint; see m3CreateSphericalJoint for the rules every create shares.
Parameters:
world: The world.def: The def, from m3DefaultGearJointDef.jointOut: Receives the new id; any failure leaves the null id there when it is not null.Returns: m3_success; m3_errorInvalid for a null world, def or jointOut, a def m3DefaultGearJointDef did not make, a null body id, the same body twice, two bodies of which neither is dynamic, an axis that is not finite or whose squared length is 1e-8 or less, or a zero or NaN ratio; m3_errorStale for a stale body; m3_errorLimit for a ratio past 1e4 either way, infinities included; m3_errorCapacity for a full joint pool; m3_errorBusy from host code the world is running. Every refusal but a full pool's and a null world's counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3CreatePulleyJoint(m3World* world, const m3PulleyJointDef* def, m3JointId* jointOut);
Creates a pulley joint; see m3CreateSphericalJoint for the rules every create shares.
Parameters:
world: The world.def: The def, from m3DefaultPulleyJointDef.jointOut: Receives the new id; any failure leaves the null id there when it is not null.Returns: m3_success; m3_errorInvalid for a null world, def or jointOut, a def m3DefaultPulleyJointDef did not make, a null body id, the same body twice, two bodies of which neither is dynamic, a NaN anchor, a NaN ground anchor, a ratio that is not positive or is NaN, or an anchor whose rope end, at the bodies' create poses, lies within 1e-3 m of its pulley; m3_errorStale for a stale body; m3_errorLimit for an anchor past M3_LOCAL_LIMIT, a ground anchor past M3_POSITION_LIMIT or a ratio past 1e4, infinities included; m3_errorCapacity for a full joint pool; m3_errorBusy from host code the world is running. Every refusal but a full pool's and a null world's counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3DestroyJoint(m3World* world, m3JointId joint);
Destroys a joint. Journaled.
Parameters:
world: The world.joint: The joint.Returns: m3_success; m3_errorInvalid for a null world or the null id; m3_errorStale for a gone joint; m3_errorBusy from host code the world is running. Each refusal but a null world's counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time.
bool m3Joint_IsValid(const m3World* world, m3JointId joint);
Returns whether the id names a live joint of this world.
Parameters:
world: The world; null gives false.joint: The id.Returns: Whether the joint is alive.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
m3JointType m3Joint_GetType(const m3World* world, m3JointId joint);
Returns the joint's type.
Parameters:
world: The world.joint: The joint.Returns: The type; m3_sphericalJoint for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
m3BodyId m3Joint_GetBodyA(const m3World* world, m3JointId joint);
Returns the joint's first body.
Parameters:
world: The world.joint: The joint.Returns: Body A's id; the null id for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
m3BodyId m3Joint_GetBodyB(const m3World* world, m3JointId joint);
Returns the joint's second body.
Parameters:
world: The world.joint: The joint.Returns: Body B's id; the null id for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3Joint_EnableLimit(m3World* world, m3JointId joint, bool enable);
Runtime joint control. All journaled; both bodies wake on any change, and each call zeroes the stored impulse of the rows it changes, so a stale warm start cannot kick. A refused call changes nothing and counts one misuse; a getter reads zeros for a stale id, which counts one misuse, and for a type without that part.
Limits: angles for revolute joints and the spherical twist, meters for prismatic and wheel joints. The range is ordered when it is set and whenever the limit is on. Other joint types take no limits; a distance joint's range is its length range below. Switches the limit on or off; the range must be ordered to switch it on. Journaled. A null world does nothing. A stale or null id, a joint that is not revolute, prismatic, spherical or wheel, switching the limit on while its bounds are out of order, or a call from host code the world is running changes nothing, is not journaled and counts one misuse. Revolute, prismatic, spherical and wheel joints have a limit. Both bodies wake, and the stored impulse of the rows it changes is zeroed.
Parameters:
world: The world.joint: The joint.enable: Whether the limit holds.Thread safety. Safe from any thread; a world is used by one thread at a time.
bool m3Joint_IsLimitEnabled(const m3World* world, m3JointId joint);
Returns whether the limit is on. Revolute, prismatic, spherical and wheel joints have a limit.
Parameters:
world: The world.joint: The joint.Returns: Whether it is; false, for a type without this part, for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3Joint_SetLimits(m3World* world, m3JointId joint, float lower, float upper);
Sets the limit range; finite, and ordered while the limit is on. Journaled. A null world does nothing. A stale or null id, a joint that is not revolute, prismatic, spherical or wheel, a bound that is not finite, a lower bound above the upper one (refused with the limit off too), or a call from host code the world is running changes nothing, is not journaled and counts one misuse. Revolute, prismatic, spherical and wheel joints have a limit. Both bodies wake, and the stored impulse of the rows it changes is zeroed.
Parameters:
world: The world.joint: The joint.lower: The lower bound, radians or meters by type.upper: The upper bound.Thread safety. Safe from any thread; a world is used by one thread at a time.
void m3Joint_GetLimits(const m3World* world, m3JointId joint, float* lowerOut, float* upperOut);
Reads the limit range. Either output may be null. Revolute, prismatic, spherical and wheel joints have a limit.
Parameters:
world: The world.joint: The joint.lowerOut: Receives the lower bound; 0, for a type without this part, for a null world, and for a stale or null id, which counts one misuse.upperOut: Receives the upper bound, as lowerOut.Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3Joint_EnableMotor(m3World* world, m3JointId joint, bool enable);
Motor: only revolute, prismatic, wheel and generic joints take one. Its speed is within 1e5 rad/s or m/s and its effort in [0, 1e20]. Switches the motor on or off. Journaled. A null world does nothing. A stale or null id, a joint that is not revolute, prismatic, wheel or generic, or a call from host code the world is running changes nothing, is not journaled and counts one misuse. Revolute, prismatic, wheel and generic joints have a motor. Both bodies wake, and the stored impulse of the rows it changes is zeroed.
Parameters:
world: The world.joint: The joint.enable: Whether the motor drives.Thread safety. Safe from any thread; a world is used by one thread at a time.
bool m3Joint_IsMotorEnabled(const m3World* world, m3JointId joint);
Returns whether the motor is on. Revolute, prismatic, wheel and generic joints have a motor.
Parameters:
world: The world.joint: The joint.Returns: Whether it is; false, for a type without this part, for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3Joint_SetMotorSpeed(m3World* world, m3JointId joint, float speed);
Sets the motor's target speed. Journaled. A null world does nothing. A stale or null id, a joint that is not revolute, prismatic, wheel or generic, a speed that is NaN or past 1e5 either way, infinities included, or a call from host code the world is running changes nothing, is not journaled and counts one misuse. Revolute, prismatic, wheel and generic joints have a motor. Both bodies wake, and the stored impulse of the rows it changes is zeroed.
Parameters:
world: The world.joint: The joint.speed: The speed, rad/s or m/s by type, within 1e5.Thread safety. Safe from any thread; a world is used by one thread at a time.
float m3Joint_GetMotorSpeed(const m3World* world, m3JointId joint);
Returns the motor's target speed. Revolute, prismatic, wheel and generic joints have a motor.
Parameters:
world: The world.joint: The joint.Returns: The speed; 0, for a type without this part, for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3Joint_SetMaxMotorEffort(m3World* world, m3JointId joint, float maxEffort);
Sets the motor's force or torque budget. Journaled. A null world does nothing. A stale or null id, a joint that is not revolute, prismatic, wheel or generic, an effort that is negative, NaN or past 1e20, infinities included, or a call from host code the world is running changes nothing, is not journaled and counts one misuse. Revolute, prismatic, wheel and generic joints have a motor. Both bodies wake, and the stored impulse of the rows it changes is zeroed.
Parameters:
world: The world.joint: The joint.maxEffort: The budget, N or N m by type, in [0, 1e20].Thread safety. Safe from any thread; a world is used by one thread at a time.
float m3Joint_GetMaxMotorEffort(const m3World* world, m3JointId joint);
Returns the motor's force or torque budget. Revolute, prismatic, wheel and generic joints have a motor.
Parameters:
world: The world.joint: The joint.Returns: The budget; 0, for a type without this part, for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3MotorJoint_SetOffsets(m3World* world, m3JointId joint, m3Vec3 linearOffset, m3Quat angularOffset);
The motor joint's aim: linearOffset is body B's target position in body A's joint frame, within 1e4 m on every axis, and angularOffset its target rotation relative to that frame, a unit quaternion within 10% that is stored normalized. A fresh servo aims at its create pose. Motor joints only, here and for the budgets: each setter refuses any other type loudly, each getter reads zeros for it, and either counts one misuse. A null world does nothing. A stale or null id, a joint that is not a motor joint, a linear offset component that is not finite or past 1e4, an angular offset that is not finite or whose squared length is outside [0.81, 1.21], or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.joint: The joint.linearOffset: Body B's target position in A's joint frame.angularOffset: B's target rotation, a quaternion within 10% of unit length.Thread safety. Safe from any thread; a world is used by one thread at a time.
m3Vec3 m3MotorJoint_GetLinearOffset(const m3World* world, m3JointId joint);
Returns the motor joint's linear aim.
Parameters:
world: The world.joint: The joint.Returns: The offset; zero for a null world, and for a stale or null id or another joint type, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
m3Quat m3MotorJoint_GetAngularOffset(const m3World* world, m3JointId joint);
Returns the motor joint's angular aim, normalized.
Parameters:
world: The world.joint: The joint.Returns: The rotation; identity for a null world, and for a stale or null id or another joint type, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3MotorJoint_SetMaxForce(m3World* world, m3JointId joint, float maxForce);
The motor joint's budgets: the force its translation drive and the torque its rotation drive may spend, each in [0, 1e20], 0 for no cap. A null world does nothing. A stale or null id, a joint that is not a motor joint, a budget that is negative, NaN or past 1e20, infinities included, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.joint: The joint.maxForce: The force budget, N, in [0, 1e20].Thread safety. Safe from any thread; a world is used by one thread at a time.
float m3MotorJoint_GetMaxForce(const m3World* world, m3JointId joint);
Returns the motor joint's force budget.
Parameters:
world: The world.joint: The joint.Returns: The budget; 0 for a null world, and for a stale or null id or another joint type, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3MotorJoint_SetMaxTorque(m3World* world, m3JointId joint, float maxTorque);
Sets the motor joint's torque budget. Journaled. A null world does nothing. A stale or null id, a joint that is not a motor joint, a budget that is negative, NaN or past 1e20, infinities included, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.joint: The joint.maxTorque: The torque budget, N m, in [0, 1e20].Thread safety. Safe from any thread; a world is used by one thread at a time.
float m3MotorJoint_GetMaxTorque(const m3World* world, m3JointId joint);
Returns the motor joint's torque budget.
Parameters:
world: The world.joint: The joint.Returns: The budget; 0 for a null world, and for a stale or null id or another joint type, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3DistanceJoint_SetLengthRange(m3World* world, m3JointId joint, float minLength, float maxLength);
The distance joint's length range in meters, 0 <= minLength <= maxLength, finite: a rod is minLength == maxLength, a rope a range. Distance joints only: the setter refuses any other type loudly, the getter reads zeros for it, and either counts one misuse. Either output may be null. Journaled. A null world does nothing. A stale or null id, a joint that is not a distance joint, a bound that is not finite, a negative minimum, a minimum above the maximum, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.joint: The joint.minLength: The shortest anchor distance, meters.maxLength: The longest, at least minLength.Thread safety. Safe from any thread; a world is used by one thread at a time.
void m3DistanceJoint_GetLengthRange(const m3World* world, m3JointId joint, float* minLengthOut, float* maxLengthOut);
Reads the distance joint's length range. Either output may be null.
Parameters:
world: The world.joint: The joint.minLengthOut: Receives the shortest distance; 0 for a null world, and for a stale or null id or another joint type, which counts one misuse.maxLengthOut: Receives the longest, as minLengthOut.Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3DistanceJoint_SetLength(m3World* world, m3JointId joint, float length);
The distance joint's spring rest length in meters, finite and not negative, which the joint spring part pulls toward while it is on. Distance joints only, as the length range. Journaled. A null world does nothing. A stale or null id, a joint that is not a distance joint, a length that is negative or not finite, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.joint: The joint.length: The rest length, meters.Thread safety. Safe from any thread; a world is used by one thread at a time.
float m3DistanceJoint_GetLength(const m3World* world, m3JointId joint);
Returns the distance joint's spring rest length.
Parameters:
world: The world.joint: The joint.Returns: The length, meters; 0 for a null world, and for a stale or null id or another joint type, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3WheelJoint_EnableSteering(m3World* world, m3JointId joint, bool enable);
Wheel steering: a soft drive about the strut axis toward a target angle. While steering is enabled, the wheel's frame-x lock becomes the drive (frame y stays locked), so the axle yaws toward the target. The target is in radians with |target| <= 1, the frequency in [0, 1e5] and positive while enabled, the damping ratio in [0, 1e4] and the torque budget in [0, 1e20], 0 for no cap. The values hold while steering is off, so set the frequency before enabling it. Wheel joints only: each setter refuses any other type loudly, each getter reads 0 for it, and either counts one misuse. Journaled. A null world does nothing. A stale or null id, a joint that is not a wheel joint, switching steering on while its hertz is zero, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.joint: The joint.enable: Whether the steering drive runs.Thread safety. Safe from any thread; a world is used by one thread at a time.
bool m3WheelJoint_IsSteeringEnabled(const m3World* world, m3JointId joint);
Returns whether the steering drive runs.
Parameters:
world: The world.joint: The joint.Returns: Whether it does; false for a null world, and for a stale or null id or another joint type, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3WheelJoint_SetTargetSteeringAngle(m3World* world, m3JointId joint, float radians);
Sets the steering target. Journaled. A null world does nothing. A stale or null id, a joint that is not a wheel joint, an angle that is NaN or past 1 radian either way, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.joint: The joint.radians: The target, within 1 radian either way.Thread safety. Safe from any thread; a world is used by one thread at a time.
float m3WheelJoint_GetTargetSteeringAngle(const m3World* world, m3JointId joint);
Returns the steering target.
Parameters:
world: The world.joint: The joint.Returns: The target, radians; 0 for a null world, and for a stale or null id or another joint type, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3WheelJoint_SetSteeringHertz(m3World* world, m3JointId joint, float hertz);
Sets the steering drive's frequency. Journaled. A null world does nothing. A stale or null id, a joint that is not a wheel joint, a hertz that is negative, NaN or past 1e5, a zero hertz while steering is on, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.joint: The joint.hertz: The frequency, in [0, 1e5], positive while steering is on.Thread safety. Safe from any thread; a world is used by one thread at a time.
float m3WheelJoint_GetSteeringHertz(const m3World* world, m3JointId joint);
Returns the steering drive's frequency.
Parameters:
world: The world.joint: The joint.Returns: The frequency; 0 for a null world, and for a stale or null id or another joint type, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3WheelJoint_SetSteeringDampingRatio(m3World* world, m3JointId joint, float dampingRatio);
Sets the steering drive's damping ratio. Journaled. A null world does nothing. A stale or null id, a joint that is not a wheel joint, a ratio that is negative, NaN or past 1e4, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.joint: The joint.dampingRatio: The ratio, in [0, 1e4].Thread safety. Safe from any thread; a world is used by one thread at a time.
float m3WheelJoint_GetSteeringDampingRatio(const m3World* world, m3JointId joint);
Returns the steering drive's damping ratio.
Parameters:
world: The world.joint: The joint.Returns: The ratio; 0 for a null world, and for a stale or null id or another joint type, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3WheelJoint_SetMaxSteeringTorque(m3World* world, m3JointId joint, float maxTorque);
Sets the steering drive's torque budget. Journaled. A null world does nothing. A stale or null id, a joint that is not a wheel joint, a torque that is negative, NaN or past 1e20, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.joint: The joint.maxTorque: The budget, N m, in [0, 1e20], 0 for no cap.Thread safety. Safe from any thread; a world is used by one thread at a time.
float m3WheelJoint_GetMaxSteeringTorque(const m3World* world, m3JointId joint);
Returns the steering drive's torque budget.
Parameters:
world: The world.joint: The joint.Returns: The budget; 0 for a null world, and for a stale or null id or another joint type, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
float m3WheelJoint_GetSteeringAngle(const m3World* world, m3JointId joint);
The current strut twist in radians (wheel joints; 0 for every other type, which counts one misuse, and stale ids).
Parameters:
world: The world.joint: The joint.Returns: The twist, radians; 0 for a null world, and for a stale or null id or another joint type, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3Joint_EnableConnectedCollision(m3World* world, m3JointId joint, bool flag);
Let (or forbid) the two jointed bodies collide with each other. Journaled; binds at the next step's pair scan. A null world does nothing. A stale or null id, or a call from host code the world is running, changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.joint: The joint.flag: Whether the two bodies collide.Thread safety. Safe from any thread; a world is used by one thread at a time.
bool m3Joint_IsConnectedCollisionEnabled(const m3World* world, m3JointId joint);
Returns whether the two jointed bodies collide.
Parameters:
world: The world.joint: The joint.Returns: Whether they do; false for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3Joint_SetBreakLimits(m3World* world, m3JointId joint, float maxForce, float maxTorque);
Breakage: rollback games need breakage as a deterministic in-step state transition, not a host poll racing the journal. When either reaction magnitude exceeds its cap at the end of a step, the joint destroys itself and emits the joint break event (see world.h). Zero disables a cap; both zero (the default) means unbreakable. Journaled. A null world does nothing. A stale or null id, a cap that is negative or not finite, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.joint: The joint.maxForce: The force cap, N, 0 for none.maxTorque: The torque cap, N m, 0 for none.Thread safety. Safe from any thread; a world is used by one thread at a time.
void m3Joint_GetBreakLimits(const m3World* world, m3JointId joint, float* maxForceOut, float* maxTorqueOut);
The break limits m3Joint_SetBreakLimits sets, 0 for a cap that is off. A stale id reads zeros and counts one misuse; a null world reads zeros. Either output may be null.
Parameters:
world: The world.joint: The joint.maxForceOut: Receives the force cap.maxTorqueOut: Receives the torque cap.Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
float m3Joint_GetReactionForce(const m3World* world, m3JointId joint);
Reaction readback: MAGNITUDES of the last step's constraint reactions, assembled per type from the stored solver rows (linear rows into force, angular rows into torque; the generic joint reports a conservative sum). Reads 0 before the first step after a restore (documented transient).
Parameters:
world: The world.joint: The joint.Returns: The force magnitude, N; 0 for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
float m3Joint_GetReactionTorque(const m3World* world, m3JointId joint);
The torque magnitude of the last step's reaction; see above.
Parameters:
world: The world.joint: The joint.Returns: The torque magnitude, N m; 0 for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
float m3Joint_GetAngle(const m3World* world, m3JointId joint);
Geometry reads: the angle about the hinge of a revolute joint, or a wheel joint's spin about its axle (radians), and the translation along a prismatic joint's slide axis or a wheel joint's suspension axis (meters). Any other type, or a stale id, reads 0 and counts one misuse.
Parameters:
world: The world.joint: The joint.Returns: The angle, radians; 0 for a null world, and for a stale or null id or a type without an angle, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
float m3Joint_GetTranslation(const m3World* world, m3JointId joint);
The translation along the slide or suspension axis; see above.
Parameters:
world: The world.joint: The joint.Returns: The translation, meters; 0 for a null world, and for a stale or null id or a type without one, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3Joint_EnableSpring(m3World* world, m3JointId joint, bool enable);
Position drive: a soft constraint with the given frequency and damping ratio pulls the joint toward its target. Revolute drives the hinge angle, prismatic and wheel the translation, spherical the relative rotation, the motor joint its aim, and the distance joint the anchor distance toward its length; other types refuse. The frequency is in [0, 1e5] Hz and positive while the spring is on, the damping ratio in [0, 1e4]. The spring keeps its values while it is off. A null world does nothing. A stale or null id, a joint that is not revolute, prismatic, spherical, wheel, motor or distance, switching the spring on while its hertz is zero, or a call from host code the world is running changes nothing, is not journaled and counts one misuse. Spherical, revolute, prismatic, wheel, motor and distance joints have a spring. Both bodies wake, and the stored impulse of the rows it changes is zeroed.
Parameters:
world: The world.joint: The joint.enable: Whether the spring pulls.Thread safety. Safe from any thread; a world is used by one thread at a time.
bool m3Joint_IsSpringEnabled(const m3World* world, m3JointId joint);
Returns whether the spring is on. Spherical, revolute, prismatic, wheel, motor and distance joints have a spring.
Parameters:
world: The world.joint: The joint.Returns: Whether it is; false, for a type without this part, for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3Joint_SetSpringHertz(m3World* world, m3JointId joint, float hertz);
Sets the spring's frequency. Journaled. A null world does nothing. A stale or null id, a joint that is not revolute, prismatic, spherical, wheel, motor or distance, a hertz that is negative, NaN or past 1e5, infinities included, a zero hertz while the spring is on, or a call from host code the world is running changes nothing, is not journaled and counts one misuse. Spherical, revolute, prismatic, wheel, motor and distance joints have a spring. Both bodies wake, and the stored impulse of the rows it changes is zeroed.
Parameters:
world: The world.joint: The joint.hertz: The frequency, in [0, 1e5], positive while the spring is on.Thread safety. Safe from any thread; a world is used by one thread at a time.
float m3Joint_GetSpringHertz(const m3World* world, m3JointId joint);
Returns the spring's frequency. Spherical, revolute, prismatic, wheel, motor and distance joints have a spring.
Parameters:
world: The world.joint: The joint.Returns: The frequency; 0, for a type without this part, for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3Joint_SetSpringDampingRatio(m3World* world, m3JointId joint, float dampingRatio);
Sets the spring's damping ratio. Journaled. A null world does nothing. A stale or null id, a joint that is not revolute, prismatic, spherical, wheel, motor or distance, a ratio that is negative, NaN or past 1e4, infinities included, or a call from host code the world is running changes nothing, is not journaled and counts one misuse. Spherical, revolute, prismatic, wheel, motor and distance joints have a spring. Both bodies wake, and the stored impulse of the rows it changes is zeroed.
Parameters:
world: The world.joint: The joint.dampingRatio: The ratio, in [0, 1e4].Thread safety. Safe from any thread; a world is used by one thread at a time.
float m3Joint_GetSpringDampingRatio(const m3World* world, m3JointId joint);
Returns the spring's damping ratio. Spherical, revolute, prismatic, wheel, motor and distance joints have a spring.
Parameters:
world: The world.joint: The joint.Returns: The ratio; 0, for a type without this part, for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3RevoluteJoint_SetTargetAngle(m3World* world, m3JointId joint, float radians);
Sets the revolute spring's target angle. Journaled. A null world does nothing. A stale or null id, a joint that is not a revolute joint, an angle that is not finite or outside [-pi, pi], or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.joint: The joint.radians: The target hinge angle, in [-pi, pi].Thread safety. Safe from any thread; a world is used by one thread at a time.
void m3Joint_SetTargetTranslation(m3World* world, m3JointId joint, float meters);
Sets the prismatic or wheel spring's target translation. Journaled. A null world does nothing. A stale or null id, a joint that is not a prismatic or wheel joint, a translation that is not finite, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.joint: The joint.meters: The target translation, finite.Thread safety. Safe from any thread; a world is used by one thread at a time.
void m3SphericalJoint_SetTargetRotation(m3World* world, m3JointId joint, m3Quat target);
The target must be a unit rotation; garbage refuses loudly by doing nothing. The target lives in the JOINT FRAMES (frame z is the create-time local axis): it is the desired rotation of frame B relative to frame A. Pick your axes at create time so the frame reads naturally. Journaled. A null world does nothing. A stale or null id, a joint that is not a spherical joint, a rotation that is not finite or whose squared length is outside [0.99, 1.01], or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.joint: The joint.target: B's target rotation relative to A, in the joint frames, a quaternion whose squared length is within 1 percent of 1.Thread safety. Safe from any thread; a world is used by one thread at a time.
void m3SphericalJoint_EnableCone(m3World* world, m3JointId joint, bool enable);
The swing cone (m3SphericalJointDef enableCone and coneAngle), switched and moved at run time; each takes effect in its own call. The angle is finite and not negative, as the create holds it. Any other joint type, a stale id or a refused value changes nothing and counts one misuse; the getters then read false and zero. Journaled. A null world does nothing. A stale or null id, a joint that is not a spherical joint, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.joint: The joint.enable: Whether the cone holds.Thread safety. Safe from any thread; a world is used by one thread at a time.
bool m3SphericalJoint_IsConeEnabled(const m3World* world, m3JointId joint);
Returns whether the cone holds.
Parameters:
world: The world.joint: The joint.Returns: Whether it does; false for a null world, and for a stale or null id or another joint type, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3SphericalJoint_SetConeAngle(m3World* world, m3JointId joint, float angle);
Sets the cone angle. Journaled. A null world does nothing. A stale or null id, a joint that is not a spherical joint, an angle that is negative or not finite (refused with the cone off too), or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.joint: The joint.angle: The angle from A's frame z, radians, finite and not negative.Thread safety. Safe from any thread; a world is used by one thread at a time.
float m3SphericalJoint_GetConeAngle(const m3World* world, m3JointId joint);
Returns the cone angle.
Parameters:
world: The world.joint: The joint.Returns: The angle; 0 for a null world, and for a stale or null id or another joint type, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
replay.hReplays: the replay container that seals a snapshot, a journal and the final hash into one artifact, and the functions that write, verify, seek and compare replays.
M3_NODISCARD M3_API m3Result m3DescribeJournal(const void* journal, int64_t bytes, m3JournalInfo* infoOut);
Counts the records of a journal tape and the steps among them, walking its framing without replaying it.
Parameters:
journal: The tape a journal wrote into its buffer, between m3World_StartJournal and m3World_StopJournal.bytes: The tape's length in bytes.infoOut: Receives the counts; any failure leaves it as it was, since the call has no owner.Returns: m3_success; m3_errorInvalid for a null tape or infoOut, a negative length or one this target cannot address; m3_errorVersion for a tape another minor version wrote; m3_errorFormat for a tape too short for its header, another format's header, a record with an op code below 1 or a negative payload length, or a record whose framing runs past the end.
Thread safety. Safe from any thread.
int64_t m3GetEncodedReplaySize(int64_t snapshotBytes, int64_t journalBytes);
Exact encoded size for the given payload sizes, or 0 when they cannot be a snapshot and a tape or the container would pass INT64_MAX bytes.
Parameters:
snapshotBytes: The snapshot's length in bytes.journalBytes: The journal tape's length in bytes.Returns: The container's length in bytes, or 0 for a length too short to hold its own header or a pair past INT64_MAX.
Thread safety. Safe from any thread.
M3_NODISCARD M3_API m3Result m3EncodeReplay(const void* snapshot, int64_t snapshotBytes, const void* journal, int64_t journalBytes, uint64_t finalHash, void* containerOut, int64_t capacity, int64_t* bytesOut);
Encode a container. finalHash is the recorder's end hash (m3World_Hash after the session); verifiers compare against it. Sets *bytesOut to the bytes written; any failure leaves it as it was, since the call has no owner. Returns m3_errorVersion for a snapshot or tape another minor version wrote, m3_errorInvalid for a null pointer or a containerOut whose first m3GetEncodedReplaySize bytes overlap the snapshot or the tape, m3_errorFormat for sizes too short to hold a snapshot or a tape, a header that is not a snapshot's or a malformed journal, m3_errorLimit for a pair whose container no buffer of this target can hold, and m3_errorCapacity for a small buffer.
Parameters:
snapshot: The session's first snapshot, as m3World_Snapshot wrote it.snapshotBytes: The snapshot's length in bytes.journal: The session's journal tape.journalBytes: The tape's length in bytes.finalHash: The recorder's m3World_Hash at the session's end.containerOut: Receives the container; it must not overlap either input.capacity: containerOut's length in bytes, at least m3GetEncodedReplaySize of the two lengths.bytesOut: Receives the container's length on success.Returns: m3_success, or one of the refusals above.
Thread safety. Safe from any thread; the buffers are used by one thread at a time.
M3_NODISCARD M3_API m3Result m3DecodeReplay(const void* data, int64_t bytes, m3ReplayView* viewOut);
Decode and validate framing (the container's header, the snapshot's and the tape's prefixes, lengths, journal record walk). Returns m3_errorVersion when another minor version wrote the container or what it holds, and m3_errorFormat on any corruption, with the view untouched either way.
Parameters:
data: The container, as m3EncodeReplay wrote it.bytes: The container's length in bytes.viewOut: Receives the view, whose pointers alias data; any failure leaves it as it was.Returns: m3_success; m3_errorInvalid for a null data or viewOut, a negative length or one this target cannot address; m3_errorVersion or m3_errorFormat as above.
Thread safety. Safe from any thread.
M3_NODISCARD M3_API m3Result m3World_Compare(const m3World* worldA, const m3World* worldB, m3BodyDiff* rowsOut, int32_t capacity, int32_t* totalOut);
Compare every body slot of two worlds, of any capacities: a slot past one world's bodies counts as missing there. Writes up to capacity rows into rowsOut, sorted worst-first, sets *totalOut to the number of differing slots, which may exceed capacity, and returns m3_success. Zero means the worlds agree body for body. A NULL rowsOut with capacity 0 measures. Returns m3_errorInvalid for a NULL world, a NULL totalOut, a negative capacity or a NULL rowsOut with a positive one, and counts one misuse on worldA, or on worldB when worldA is NULL. A refusal sets a given totalOut to 0 and, when rowsOut and capacity pass, zeroes rowsOut over its whole capacity; a success writes only its rows. It only reads, so it is never refused as busy.
Parameters:
worldA: The first world. A row's id carries its slot with world A's generation when the body is alive in A, and world B's on an onlyInB row.worldB: The second world.rowsOut: Receives up to capacity rows, worst first; null with capacity 0 measures.capacity: rowsOut's length in rows, at least 0.totalOut: Receives the number of differing body slots.Returns: m3_success, or m3_errorInvalid as above.
Thread safety. Safe from any thread; each world is used by one thread at a time, or by several readers at once.
shape.hShapes: geometry, materials, filters, compounds, meshes, heightfields and voxel chunks.
m3ShapeDef m3DefaultShapeDef(void);
Returns a def with pinned defaults (density 1, friction 0.6, restitution 0) and a valid cookie.
Returns: The def, with the cookie the creates check.
Thread safety. Safe from any thread.
M3_NODISCARD M3_API m3Result m3CreateSphereShape(m3World* world, m3BodyId body, const m3ShapeDef* def, const m3Sphere* sphere, m3ShapeId* shapeOut);
Create a sphere on a body and recompute the body's mass from its shapes (sphere mass = density * 4/3 pi r^3, inertia 0.4 m r^2). Every shape create leaves *shapeOut the null id on any failure, and changes nothing else. Journaled.
Parameters:
world: The world.body: The body the shape joins.def: The def, from m3DefaultShapeDef.sphere: The sphere, in the shape's frame.shapeOut: Receives the new id; any failure leaves the null id there when it is not null.Returns: m3_success; m3_errorInvalid for a null world, def or shapeOut, the null body id, a body a character owns, a def m3DefaultShapeDef did not make, a def localRotation that is not finite or whose squared length is outside [0.99, 1.01], a NaN in the def's localPosition, restitution or surfaceVelocity, a density that is not positive or is NaN, a friction or rolling resistance that is negative or not finite, a negative restitution, a null sphere, a NaN center, or a radius that is not positive or is NaN; m3_errorLimit for a def localPosition component past M3_LOCAL_LIMIT, a density past M3_DENSITY_LIMIT, a restitution past M3_RATIO_LIMIT, a surfaceVelocity component past M3_SPEED_LIMIT, or a center component or radius past M3_LOCAL_LIMIT, infinities included, or a shape below the mass floors of a dynamic body; m3_errorLimit, counting no misuse, for a body mass the shape would carry past M3_MASS_LIMIT or a joint on the body it would carry past its lever ratio; m3_errorCapacity, counting no misuse, for a full shape pool or an allocator that refuses the shape's broadphase entry; m3_errorStale for a stale body; m3_errorBusy from host code the world is running. Every refusal counts one misuse but those marked as counting none and any with a null world.
Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3CreatePlaneShape(m3World* world, m3BodyId body, const m3ShapeDef* def, const m3Plane* plane, m3ShapeId* shapeOut);
Create a half-space on a STATIC body (a plane on a dynamic body returns m3_errorInvalid). The normal is normalized on create, and the offset is within M3_POSITION_LIMIT like every position: a farther plane returns m3_errorLimit. Journaled.
Parameters:
world: The world.body: The body the shape joins.def: The def, from m3DefaultShapeDef.plane: The half-space, in the body's frame.shapeOut: Receives the new id; any failure leaves the null id there when it is not null.Returns: m3_success; m3_errorInvalid for a null world, def or shapeOut, the null body id, a body a character owns, a def m3DefaultShapeDef did not make, a def localRotation that is not finite or whose squared length is outside [0.99, 1.01], a NaN in the def's localPosition, restitution or surfaceVelocity, a density that is not positive or is NaN, a friction or rolling resistance that is negative or not finite, a negative restitution, a null plane, a normal that is not finite or is near zero, a NaN offset, or a body that is not static; m3_errorLimit for a def localPosition component past M3_LOCAL_LIMIT, a density past M3_DENSITY_LIMIT, a restitution past M3_RATIO_LIMIT, a surfaceVelocity component past M3_SPEED_LIMIT, or an offset past M3_POSITION_LIMIT, infinities included; m3_errorCapacity, counting no misuse, for a full shape pool; m3_errorStale for a stale body; m3_errorBusy from host code the world is running. Every refusal counts one misuse but those marked as counting none and any with a null world.
Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3CreateBoxShape(m3World* world, m3BodyId body, const m3ShapeDef* def, m3Vec3 halfExtents, m3ShapeId* shapeOut);
Create a box (a convex hull with analytic mass properties: m = 8 rho hx hy hz, I = m/3 diag(hy^2+hz^2, ...) about the center). Half extents are positive and at most 1e4. A box is a hull: it collides, casts and sweeps as one. Journaled.
Parameters:
world: The world.body: The body the shape joins.def: The def, from m3DefaultShapeDef.halfExtents: The half extents, each positive and at most 1e4 m.shapeOut: Receives the new id; any failure leaves the null id there when it is not null.Returns: m3_success; m3_errorInvalid for a null world, def or shapeOut, the null body id, a body a character owns, a def m3DefaultShapeDef did not make, a def localRotation that is not finite or whose squared length is outside [0.99, 1.01], a NaN in the def's localPosition, restitution or surfaceVelocity, a density that is not positive or is NaN, a friction or rolling resistance that is negative or not finite, a negative restitution, or a half extent that is not positive or is NaN; m3_errorLimit for a def localPosition component past M3_LOCAL_LIMIT, a density past M3_DENSITY_LIMIT, a restitution past M3_RATIO_LIMIT, a surfaceVelocity component past M3_SPEED_LIMIT, or a half extent past M3_LOCAL_LIMIT, infinities included, or a shape below the mass floors of a dynamic body; m3_errorLimit, counting no misuse, for a body mass the shape would carry past M3_MASS_LIMIT or a joint on the body it would carry past its lever ratio; m3_errorCapacity, counting no misuse, for a full shape or hull pool, or an allocator that refuses the hull or the shape's broadphase entry; m3_errorStale for a stale body; m3_errorBusy from host code the world is running. Every refusal counts one misuse but those marked as counting none and any with a null world.
Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3CreateCapsuleShape(m3World* world, m3BodyId body, const m3ShapeDef* def, const m3Capsule* capsule, m3ShapeId* shapeOut);
A capsule: the segment point1..point2 inflated by radius. A zero-length segment is refused (that shape is a sphere; use m3CreateSphereShape). Journaled.
Parameters:
world: The world.body: The body the shape joins.def: The def, from m3DefaultShapeDef.capsule: The capsule, in the shape's frame.shapeOut: Receives the new id; any failure leaves the null id there when it is not null.Returns: m3_success; m3_errorInvalid for a null world, def or shapeOut, the null body id, a body a character owns, a def m3DefaultShapeDef did not make, a def localRotation that is not finite or whose squared length is outside [0.99, 1.01], a NaN in the def's localPosition, restitution or surfaceVelocity, a density that is not positive or is NaN, a friction or rolling resistance that is negative or not finite, a negative restitution, a null capsule, a NaN point, a radius that is not positive or is NaN, or a zero-length segment; m3_errorLimit for a def localPosition component past M3_LOCAL_LIMIT, a density past M3_DENSITY_LIMIT, a restitution past M3_RATIO_LIMIT, a surfaceVelocity component past M3_SPEED_LIMIT, or a point component or radius past M3_LOCAL_LIMIT, infinities included, or a shape below the mass floors of a dynamic body; m3_errorLimit, counting no misuse, for a body mass the shape would carry past M3_MASS_LIMIT or a joint on the body it would carry past its lever ratio; m3_errorCapacity, counting no misuse, for a full shape pool or an allocator that refuses the shape's broadphase entry; m3_errorStale for a stale body; m3_errorBusy from host code the world is running. Every refusal counts one misuse but those marked as counting none and any with a null world.
Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3CreateCylinderShape(m3World* world, m3BodyId body, const m3ShapeDef* def, const m3Cylinder* cylinder, int32_t segments, m3ShapeId* shapeOut);
Create a faceted cylinder: a prism of 2 * segments vertices, built and refused by m3CreateHullShape, so its mass, contacts and casts are the prism's exactly. The side is a segments-gon, not a curve; 24 segments roll visually smooth at meter scales. Segments clamp to [3, 32] and are never refused. Journaled.
Parameters:
world: The world.body: The body the shape joins.def: The def, from m3DefaultShapeDef.cylinder: The cylinder, in the shape's frame.segments: The side's facet count, clamped to [3, 32].shapeOut: Receives the new id; any failure leaves the null id there when it is not null.Returns: m3_success; m3_errorInvalid for a null world, def or shapeOut, the null body id, a body a character owns, a def m3DefaultShapeDef did not make, a def localRotation that is not finite or whose squared length is outside [0.99, 1.01], a NaN in the def's localPosition, restitution or surfaceVelocity, a density that is not positive or is NaN, a friction or rolling resistance that is negative or not finite, a negative restitution, a null cylinder, a NaN cap point, a radius that is not positive or is NaN, a zero-length axis, or a prism the hull builder finds degenerate; m3_errorLimit for a def localPosition component past M3_LOCAL_LIMIT, a density past M3_DENSITY_LIMIT, a restitution past M3_RATIO_LIMIT, a surfaceVelocity component past M3_SPEED_LIMIT, a cap point component or radius past M3_LOCAL_LIMIT, or a prism vertex past it, infinities included, or a shape below the mass floors of a dynamic body; m3_errorLimit, counting no misuse, for a body mass the shape would carry past M3_MASS_LIMIT or a joint on the body it would carry past its lever ratio; m3_errorCapacity, counting no misuse, for a full shape or hull pool, or an allocator that refuses the hull builder's memory, the hull or the shape's broadphase entry; m3_errorStale for a stale body; m3_errorBusy from host code the world is running. Every refusal counts one misuse but those marked as counting none and any with a null world.
Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3Shape_SetSphere(m3World* world, m3ShapeId shape, const m3Sphere* sphere);
Runtime geometry replacement: swap a sphere or capsule shape's geometry in place; conversions between the two are legal. Hulls, meshes, voxels, and planes refuse loudly (interned slabs are immutable by law). Journaled; mass, extents, and the broadphase follow, and sleepers around both the old and the new bounds wake. The new geometry takes the create's bounds. Returns m3_success; m3_errorLimit when the body's total mass would pass M3_MASS_LIMIT or a joint on it its lever ratio, which changes nothing and counts no misuse; m3_errorStale for a stale id, m3_errorInvalid for the null id, a shape of another kind, a character's capsule or bad geometry, m3_errorLimit for geometry past a bound or a shape below the mass floors, and m3_errorBusy inside a step callback, which change nothing and count one misuse.
Parameters:
world: The world.shape: The shape.sphere: The new sphere; null is refused as invalid.Returns: m3_success, or one of the refusals above.
Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3Shape_SetCapsule(m3World* world, m3ShapeId shape, const m3Capsule* capsule);
Replaces a sphere or capsule shape's geometry with a capsule, as m3Shape_SetSphere does with a sphere.
Parameters:
world: The world.shape: The shape.capsule: The new capsule; null is refused as invalid.Returns: m3_success, or a refusal as m3Shape_SetSphere lists.
Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3CreateHullShape(m3World* world, m3BodyId body, const m3ShapeDef* def, const m3Vec3* points, int32_t count, m3ShapeId* shapeOut);
A convex hull built from a point cloud (QuickHull, coplanar faces merged, mass integrated). Between 4 and M3_MAX_HULL_POINTS points, each coordinate within M3_LOCAL_LIMIT of the body origin. A point within 512 times the builder's tolerance (16 FLT_EPSILON of the cloud's summed extents) of an earlier point is merged into it, so the hull may lose detail up to about 1e-3 of the summed extents. Degenerate clouds (coplanar, collinear, or fewer than four points once merged) return m3_errorInvalid, and a cloud of more than M3_MAX_HULL_POINTS points m3_errorLimit. An allocator that refuses the builder's working memory returns m3_errorCapacity, with the world as it was. A hull keeps at most 64 vertices; the builder stops adding points there. Journaled.
Parameters:
world: The world.body: The body the shape joins.def: The def, from m3DefaultShapeDef.points: The cloud, in the shape's frame.count: The number of points, 4 to M3_MAX_HULL_POINTS.shapeOut: Receives the new id; any failure leaves the null id there when it is not null.Returns: m3_success; m3_errorInvalid for a null world, def or shapeOut, the null body id, a body a character owns, a def m3DefaultShapeDef did not make, a def localRotation that is not finite or whose squared length is outside [0.99, 1.01], a NaN in the def's localPosition, restitution or surfaceVelocity, a density that is not positive or is NaN, a friction or rolling resistance that is negative or not finite, a negative restitution, null points, a count of 0 or less, a NaN point, or a degenerate cloud: coplanar, collinear, or fewer than four points once merged; m3_errorLimit for a def localPosition component past M3_LOCAL_LIMIT, a density past M3_DENSITY_LIMIT, a restitution past M3_RATIO_LIMIT, a surfaceVelocity component past M3_SPEED_LIMIT, a count past M3_MAX_HULL_POINTS, or a point component past M3_LOCAL_LIMIT, infinities included, or a shape below the mass floors of a dynamic body; m3_errorLimit, counting no misuse, for a body mass the shape would carry past M3_MASS_LIMIT or a joint on the body it would carry past its lever ratio; m3_errorCapacity, counting no misuse, for a full shape or hull pool, or an allocator that refuses the builder's memory, the hull or the shape's broadphase entry; m3_errorStale for a stale body; m3_errorBusy from host code the world is running. Every refusal counts one misuse but those marked as counting none and any with a null world.
Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3CreateMeshShape(m3World* world, m3BodyId body, const m3ShapeDef* def, const m3Vec3* vertices, int32_t vertexCount, const uint16_t* indices, int32_t triangleCount, m3ShapeId* shapeOut);
A static triangle mesh (level geometry, voxel chunk surfaces). Static bodies only; up to M3_MAX_MESH_VERTICES vertices and M3_MAX_MESH_TRIANGLES triangles per mesh, three indices each, counter-clockwise from outside: contacts cull the back side. Every vertex lies within M3_GEOMETRY_LIMIT of the body origin. Ghost collisions on shared edges are filtered by feature welding. A dynamic body, an index past the vertices or a NaN vertex returns m3_errorInvalid; a count or a vertex past its bound m3_errorLimit. Journaled.
Parameters:
world: The world.body: The body the shape joins.def: The def, from m3DefaultShapeDef.vertices: The vertices, in the shape's frame.vertexCount: The number of vertices, 3 to M3_MAX_MESH_VERTICES.indices: Three vertex indices per triangle.triangleCount: The number of triangles, 1 to M3_MAX_MESH_TRIANGLES.shapeOut: Receives the new id; any failure leaves the null id there when it is not null.Returns: m3_success; m3_errorInvalid for a null world, def or shapeOut, the null body id, a body a character owns, a def m3DefaultShapeDef did not make, a def localRotation that is not finite or whose squared length is outside [0.99, 1.01], a NaN in the def's localPosition, restitution or surfaceVelocity, a density that is not positive or is NaN, a friction or rolling resistance that is negative or not finite, a negative restitution, null vertices or indices, fewer than 3 vertices or 1 triangle, an index past the vertices, a NaN vertex, or a body that is not static; m3_errorLimit for a def localPosition component past M3_LOCAL_LIMIT, a density past M3_DENSITY_LIMIT, a restitution past M3_RATIO_LIMIT, a surfaceVelocity component past M3_SPEED_LIMIT, a vertex count past M3_MAX_MESH_VERTICES, a triangle count past M3_MAX_MESH_TRIANGLES, or a vertex component past M3_GEOMETRY_LIMIT, infinities included; m3_errorCapacity, counting no misuse, for a full shape or mesh pool, or an allocator that refuses the mesh, its build memory or the shape's broadphase entry; m3_errorStale for a stale body; m3_errorBusy from host code the world is running. Every refusal counts one misuse but those marked as counting none and any with a null world.
Thread safety. Safe from any thread; a world is used by one thread at a time.
void m3MeshShape_SetMaterials(m3World* world, m3ShapeId shape, const m3MeshSurfaceMaterial* materials, int32_t materialCount, const uint8_t* triangleMaterials);
Paint material groups onto a mesh shape: up to 8 entries and one group index byte per triangle (triangleMaterials, length = the mesh's triangle count, every byte < materialCount). Journaled; refuses loudly on a non-mesh shape, hostile values, or out-of-range group bytes. A mesh without painted materials keeps using its shape material everywhere. A stale or null id, a refused value, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.shape: The shape.materials: The materials, materialCount of them.materialCount: The number of materials, 1 to M3_MAX_MESH_MATERIALS.triangleMaterials: One material index per triangle.Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3CreateHeightFieldMeshShape(m3World* world, m3BodyId body, const m3ShapeDef* def, const float* heights, int32_t nx, int32_t nz, float cellSize, m3ShapeId* shapeOut);
A heightfield chunk: an nx by nz grid of heights (row-major, x fastest) spaced cellSize apart in x and z, triangulated into a static mesh through the same welded triangle path. Grid limits per chunk: 2 to M3_MAX_HEIGHTFIELD_MESH_SIZE in each direction; larger terrain tiles as chunks, the voxel-world model. The cell size is positive and within M3_CELL_LIMIT, and every height within M3_GEOMETRY_LIMIT; past either is m3_errorLimit. The grid's minimum corner sits at the body origin. Journaled.
Parameters:
world: The world.body: The body the shape joins.def: The def, from m3DefaultShapeDef.heights: nx * nz heights, row-major with x fastest.nx: The samples along x, 2 to M3_MAX_HEIGHTFIELD_MESH_SIZE.nz: The samples along z, 2 to M3_MAX_HEIGHTFIELD_MESH_SIZE.cellSize: The spacing, meters, positive and within M3_CELL_LIMIT.shapeOut: Receives the new id; any failure leaves the null id there when it is not null.Returns: m3_success; m3_errorInvalid for a null world, def or shapeOut, the null body id, a body a character owns, a def m3DefaultShapeDef did not make, a def localRotation that is not finite or whose squared length is outside [0.99, 1.01], a NaN in the def's localPosition, restitution or surfaceVelocity, a density that is not positive or is NaN, a friction or rolling resistance that is negative or not finite, a negative restitution, null heights, fewer than 2 samples along an axis, a cell size that is not positive or is NaN, a NaN height, or a body that is not static; m3_errorLimit for a def localPosition component past M3_LOCAL_LIMIT, a density past M3_DENSITY_LIMIT, a restitution past M3_RATIO_LIMIT, a surfaceVelocity component past M3_SPEED_LIMIT, a sample count past M3_MAX_HEIGHTFIELD_MESH_SIZE along an axis, a cell size past M3_CELL_LIMIT, or a height past M3_GEOMETRY_LIMIT, infinities included; m3_errorCapacity, counting no misuse, for a full shape or mesh pool, or an allocator that refuses the grid's staging, the mesh, its build memory or the shape's broadphase entry; m3_errorStale for a stale body; m3_errorBusy from host code the world is running. Every refusal counts one misuse but those marked as counting none and any with a null world.
Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3CreateHeightFieldShape(m3World* world, m3BodyId body, const m3ShapeDef* def, const float* heights, int32_t nx, int32_t nz, float cellSize, m3ShapeId* shapeOut);
The NATIVE grid heightfield: the same nx-by-nz grid contract as above, but stored as raw heights (four bytes per sample) instead of triangulated into a mesh: the low-memory terrain path. Grid limits per chunk: 2 to M3_MAX_HEIGHTFIELD_SIZE in each direction; larger terrain tiles as chunks. The cell size and the heights are bounded as above. Static bodies only; the minimum corner sits at the body origin. Rays, contacts, overlaps, shape casts, movers and continuous collision all see its triangles. Journaled.
Parameters:
world: The world.body: The body the shape joins.def: The def, from m3DefaultShapeDef.heights: nx * nz heights, row-major with x fastest.nx: The samples along x, 2 to M3_MAX_HEIGHTFIELD_SIZE.nz: The samples along z, 2 to M3_MAX_HEIGHTFIELD_SIZE.cellSize: The spacing, meters, positive and within M3_CELL_LIMIT.shapeOut: Receives the new id; any failure leaves the null id there when it is not null.Returns: m3_success; m3_errorInvalid for a null world, def or shapeOut, the null body id, a body a character owns, a def m3DefaultShapeDef did not make, a def localRotation that is not finite or whose squared length is outside [0.99, 1.01], a NaN in the def's localPosition, restitution or surfaceVelocity, a density that is not positive or is NaN, a friction or rolling resistance that is negative or not finite, a negative restitution, null heights, a body that is not static, fewer than 2 samples along an axis, a cell size that is not positive or is NaN, or a NaN height; m3_errorLimit for a def localPosition component past M3_LOCAL_LIMIT, a density past M3_DENSITY_LIMIT, a restitution past M3_RATIO_LIMIT, a surfaceVelocity component past M3_SPEED_LIMIT, a sample count past M3_MAX_HEIGHTFIELD_SIZE along an axis, a cell size past M3_CELL_LIMIT, or a height past M3_GEOMETRY_LIMIT, infinities included; m3_errorCapacity, counting no misuse, for a full shape or height field pool, or an allocator that refuses the samples or the shape's broadphase entry; m3_errorStale for a stale body; m3_errorBusy from host code the world is running. Every refusal counts one misuse but those marked as counting none and any with a null world.
Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3CreateVoxelChunkShape(m3World* world, m3BodyId body, const m3ShapeDef* def, const uint8_t* voxels, const uint16_t* payload, float cellSize, m3ShapeId* shapeOut);
A voxel chunk: a dense 16x16x16 grid anchored at the body origin, cells of cellSize meters, positive and within M3_CELL_LIMIT. voxels is one byte per voxel (zero = empty), x fastest then y then z; payload is an optional uint16 per voxel (material, health, type), carried as state and hashed. Static bodies only; sensors refused (sensor volumes are convex by contract); an empty grid refused. Solid voxels are CLOSED volumes: point-inside answers true inside filled cells. Rays, contacts, shape casts, and continuous collision all see voxel chunks; fast bodies and bullets sweep the merged surface, so a one-voxel-thick wall stops a bullet, and a wall whose voxel was cleared last step is a REAL hole.
Seam welding: chunks weld automatically when both bodies carry the exact identity rotation, cell sizes match, and world positions differ by exactly one chunk extent along one axis (grid-laid level geometry). Welded borders are interior geometry and never produce contact features, so bodies roll and slide across chunk boundaries without seam impulses. Rotated or misaligned chunks still collide correctly; they just do not weld. Journaled.
Parameters:
world: The world.body: The body the shape joins.def: The def, from m3DefaultShapeDef.voxels: 4096 occupancy bytes, x fastest then y then z.payload: 4096 payload values in the same order, or null for zeros.cellSize: The cell size, meters, positive and within M3_CELL_LIMIT.shapeOut: Receives the new id; any failure leaves the null id there when it is not null.Returns: m3_success; m3_errorInvalid for a null world, def or shapeOut, the null body id, a body a character owns, a def m3DefaultShapeDef did not make, a def localRotation that is not finite or whose squared length is outside [0.99, 1.01], a NaN in the def's localPosition, restitution or surfaceVelocity, a density that is not positive or is NaN, a friction or rolling resistance that is negative or not finite, a negative restitution, null voxels, a cell size that is not positive or is NaN, a body that is not static, a sensor def, or an empty grid; m3_errorLimit for a def localPosition component past M3_LOCAL_LIMIT, a density past M3_DENSITY_LIMIT, a restitution past M3_RATIO_LIMIT, a surfaceVelocity component past M3_SPEED_LIMIT, or a cell size past M3_CELL_LIMIT, infinities included; m3_errorCapacity, counting no misuse, for a full shape or voxel pool, an allocator that refuses the chunk, its surface or the shape's broadphase entry, or a grid whose surface passes M3_MAX_VOXEL_SURFACE_BOXES; m3_errorStale for a stale body; m3_errorBusy from host code the world is running. Every refusal counts one misuse but those marked as counting none and any with a null world.
Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3VoxelChunkShape_SetVoxel(m3World* world, m3ShapeId shape, int32_t x, int32_t y, int32_t z, uint16_t payload);
Voxel edits: deterministic state transitions, journaled and replayed like every other mutation, fully inside the rollback delta. The collision surface rebuilds as a pure function of the grid after any occupancy change (a payload-only set touches no geometry), and dynamic bodies whose bounds touch the edited region are woken (a floor vanishing under a sleeper is a disturbance). Coordinates are voxel indices in [0, 15]; out-of-range and inverted regions refuse loudly. A chunk edited down to empty stays a valid shape that collides with nothing (the natural end state of destruction).
Each edit returns m3_success when it landed; m3_errorStale for a stale id, m3_errorInvalid for the null id, a non-voxel shape or a bad argument, and m3_errorBusy inside a step callback, each counting one misuse. A chunk's surface holds at most M3_MAX_VOXEL_SURFACE_BOXES merged boxes; the slot reserved that much when its first chunk was created, so no edit asks the allocator. An edit whose surface would pass the bound returns m3_errorLimit: it changes nothing, journals nothing and counts no misuse, only m3Counters.voxelEditsRefused; a carve m3World_Explode loses to the bound counts in voxelCarvesDropped instead. A create whose grid passes it is refused with m3_errorCapacity.
The anchor convention: an island is anchored through the CHUNK's y = 0 base layer, not through world ground. Build structures at their chunk's base; a floating platform is a chunk whose BODY sits in the air with the platform at local y = 0. Voxels with no path to the base layer survive creation but fragment on the first clearing edit anywhere in the chunk (the sweep is chunk-wide by design).
Parameters:
world: The world.shape: The shape.x: The voxel's x index, 0 to 15.y: The voxel's y index, 0 to 15.z: The voxel's z index, 0 to 15.payload: The value the voxel carries.Returns: m3_success, or one of the refusals above.
Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3VoxelChunkShape_ClearVoxel(m3World* world, m3ShapeId shape, int32_t x, int32_t y, int32_t z);
Clears one voxel; an edit as m3VoxelChunkShape_SetVoxel describes.
Parameters:
world: The world.shape: The shape.x: The voxel's x index, 0 to 15.y: The voxel's y index, 0 to 15.z: The voxel's z index, 0 to 15.Returns: m3_success, or a refusal as m3VoxelChunkShape_SetVoxel lists.
Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3VoxelChunkShape_ClearBox(m3World* world, m3ShapeId shape, const int32_t lo[3], const int32_t hi[3], int32_t* clearedOut);
Clears the inclusive box [lo, hi] per axis and writes the number of voxels it cleared to clearedOut (zero is legal). A busy refusal leaves clearedOut as it was; any other failure zeroes it, and a NULL clearedOut is refused with m3_errorInvalid.
Parameters:
world: The world.shape: The shape.lo: The box's lower voxel indices, each 0 to 15.hi: The box's upper voxel indices, each at least lo's.clearedOut: Receives how many voxels were cleared.Returns: m3_success, or a refusal as m3VoxelChunkShape_SetVoxel lists, with m3_errorInvalid also for a null lo, hi or clearedOut.
Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3VoxelChunkShape_SetFill(m3World* world, m3ShapeId shape, int32_t x, int32_t y, int32_t z, uint8_t fill);
Fill fraction: 255 is a whole voxel, 1 a sliver. A mass and destruction property, never geometry: the voxel still collides as a full box, but its fragment mass scales by fill / 255. Refuses zero fill (that is a clear: use m3VoxelChunkShape_ClearVoxel) and empty voxels. Journaled state, hashed, inside the rollback delta like every edit.
Parameters:
world: The world.shape: The shape.x: The voxel's x index, 0 to 15.y: The voxel's y index, 0 to 15.z: The voxel's z index, 0 to 15.fill: The fill, 1 to 255.Returns: m3_success, or a refusal as m3VoxelChunkShape_SetVoxel lists.
Thread safety. Safe from any thread; a world is used by one thread at a time.
bool m3Shape_IsValid(const m3World* world, m3ShapeId shape);
True while the id names a live shape of this world; false for the null id and stale generations, without counting misuse.
Parameters:
world: The world; null gives false.shape: The id.Returns: Whether the shape is alive.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
m3BodyId m3Shape_GetBody(const m3World* world, m3ShapeId shape);
The owning body, so a mover can tell its own shape from the world's. Null id for stale shapes.
Parameters:
world: The world.shape: The shape.Returns: The body's id; the null id for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
m3ShapeType m3Shape_GetType(const m3World* world, m3ShapeId shape);
Returns the shape's kind.
Parameters:
world: The world.shape: The shape.Returns: The kind; m3_sphereShape for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
uint64_t m3Shape_GetUserData(const m3World* world, m3ShapeId shape);
Returns the host's value the def or m3Shape_SetUserData set.
Parameters:
world: The world.shape: The shape.Returns: The value; 0 for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3Shape_SetUserData(m3World* world, m3ShapeId shape, uint64_t userData);
Sets the host's value, carried unchanged. Journaled. A stale or null id, a refused value, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.shape: The shape.userData: The value.Thread safety. Safe from any thread; a world is used by one thread at a time.
bool m3Shape_IsSensor(const m3World* world, m3ShapeId shape);
Returns whether the shape is a sensor.
Parameters:
world: The world.shape: The shape.Returns: Whether it is; false for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
m3WorldAabb m3Shape_GetAabb(const m3World* world, m3ShapeId shape);
Returns the shape's broadphase bounds, margin included.
Parameters:
world: The world.shape: The shape.Returns: The bounds; a box at the origin for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
int32_t m3Shape_GetContactData(const m3World* world, m3ShapeId shape, m3ContactData* dataOut, int32_t capacity);
Who touches this shape now: fills up to capacity entries and returns the total, which may exceed capacity; a NULL array with capacity 0 measures. A stale shape is a refusal. A refusal zeroes the array over its whole capacity; a success, an empty one included, writes only its entries; a list call only reads, so none is refused as busy. See m3ContactData.
Parameters:
world: The world.shape: The shape.dataOut: Receives up to capacity contacts.capacity: dataOut's length, at least 0.Returns: The total number of the shape's touching contacts; 0 on a refusal.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
M3_NODISCARD M3_API m3Result m3DestroyShape(m3World* world, m3ShapeId shape);
Destroy one shape and rebuild the owner's mass books. Journaled; contacts involving the shape dissolve at the next step. The last shape leaves a shapeless dynamic body at unit mass. Refused with m3_errorLimit, counting no misuse, when a joint on the owner would pass its lever ratio at the mass left.
Parameters:
world: The world.shape: The shape.Returns: m3_success; m3_errorLimit as above; m3_errorInvalid for a null world, the null id or a character's capsule; m3_errorStale for a gone shape; m3_errorBusy from host code the world is running. Each refusal but the lever's and a null world's counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time.
void m3Shape_SetFriction(m3World* world, m3ShapeId shape, float friction);
Runtime material setters, with the def's bounds. Journaled; contacts read materials at prepare, so changes bind from the next step. A sleeping stack keeps its old mix until something wakes it. A stale or null id, a refused value, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.shape: The shape.friction: The friction, finite and not negative.Thread safety. Safe from any thread; a world is used by one thread at a time.
float m3Shape_GetFriction(const m3World* world, m3ShapeId shape);
Returns the shape's friction.
Parameters:
world: The world.shape: The shape.Returns: The friction; 0 for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3Shape_SetRestitution(m3World* world, m3ShapeId shape, float restitution);
Sets the shape's restitution. Journaled; contacts read it at prepare, so it binds from the next step. A stale or null id, a refused value, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.shape: The shape.restitution: The restitution, 0 to 1e4.Thread safety. Safe from any thread; a world is used by one thread at a time.
float m3Shape_GetRestitution(const m3World* world, m3ShapeId shape);
Returns the shape's restitution.
Parameters:
world: The world.shape: The shape.Returns: The restitution; 0 for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3Shape_SetRollingResistance(m3World* world, m3ShapeId shape, float value);
Sets the shape's rolling resistance. Journaled; contacts read it at prepare, so it binds from the next step. A stale or null id, a refused value, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.shape: The shape.value: The resistance, finite and not negative.Thread safety. Safe from any thread; a world is used by one thread at a time.
float m3Shape_GetRollingResistance(const m3World* world, m3ShapeId shape);
Returns the shape's rolling resistance.
Parameters:
world: The world.shape: The shape.Returns: The resistance; 0 for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
M3_NODISCARD M3_API m3Result m3Shape_SetDensity(m3World* world, m3ShapeId shape, float density);
Set the density and rebuild the owning body's mass, center and inertia from all its shapes: a body's mass is always its shapes'. Journaled. Returns m3_success; m3_errorLimit when a dynamic body's total mass would pass M3_MASS_LIMIT or a joint on it its lever ratio, which changes nothing and counts no misuse; m3_errorStale for a stale id, m3_errorInvalid for the null id or a density that is not positive or is NaN, m3_errorLimit for one past M3_DENSITY_LIMIT or a shape below the mass floors, and m3_errorBusy inside a step callback, which change nothing and count one misuse.
Parameters:
world: The world.shape: The shape.density: The density, kg/m^3.Returns: m3_success, or one of the refusals above.
Thread safety. Safe from any thread; a world is used by one thread at a time.
float m3Shape_GetDensity(const m3World* world, m3ShapeId shape);
Returns the shape's density.
Parameters:
world: The world.shape: The shape.Returns: The density, kg/m^3; 0 for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3Shape_EnableHitEvents(m3World* world, m3ShapeId shape, bool flag);
Opt a shape into hit events / the pre-solve veto. Journaled; the flags are state and snapshot with the world. A stale or null id, a refused value, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.shape: The shape.flag: Whether the shape reports hit events.Thread safety. Safe from any thread; a world is used by one thread at a time.
bool m3Shape_IsHitEventsEnabled(const m3World* world, m3ShapeId shape);
Returns whether the shape reports hit events.
Parameters:
world: The world.shape: The shape.Returns: Whether it does; false for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3Shape_EnablePreSolveEvents(m3World* world, m3ShapeId shape, bool flag);
Opts the shape into the pre-solve veto. Journaled. A stale or null id, a refused value, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.shape: The shape.flag: Whether the pre-solve callback sees the shape's contacts.Thread safety. Safe from any thread; a world is used by one thread at a time.
bool m3Shape_IsPreSolveEventsEnabled(const m3World* world, m3ShapeId shape);
Returns whether the shape takes part in the pre-solve veto.
Parameters:
world: The world.shape: The shape.Returns: Whether it does; false for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
M3_NODISCARD M3_API m3Result m3Shape_SetFilter(m3World* world, m3ShapeId shape, uint64_t categoryBits, uint64_t maskBits, int32_t groupIndex);
The collision filter, changed at runtime: shapes it touched wake and every pair is filtered again on the next step. Journaled. Returns m3_success; m3_errorLimit when the filter lets a shape of a dynamic body collide that did not, and its reach would pass the body's M3_CONTACT_LEVER_LIMIT, which changes nothing and counts no misuse; m3_errorStale for a stale id, m3_errorInvalid for the null id or a NULL world, and m3_errorBusy inside a step callback, which change nothing and count one misuse. GetFilter's out pointers may be NULL.
Parameters:
world: The world.shape: The shape.categoryBits: The categories the shape belongs to.maskBits: The categories it collides with.groupIndex: The group; see m3ShapeDef.Returns: m3_success, or one of the refusals above.
Thread safety. Safe from any thread; a world is used by one thread at a time.
void m3Shape_GetFilter(const m3World* world, m3ShapeId shape, uint64_t* categoryBitsOut, uint64_t* maskBitsOut, int32_t* groupIndexOut);
Reads the shape's collision filter.
Parameters:
world: The world.shape: The shape.categoryBitsOut: Receives the categories, 0 for a missing shape; may be null.maskBitsOut: Receives the mask, 0 for a missing shape; may be null.groupIndexOut: Receives the group, 0 for a missing shape; may be null.Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3Shape_SetSurfaceVelocity(m3World* world, m3ShapeId shape, m3Vec3 velocity);
Conveyor: a world-frame surface velocity on the shape. Contacts drive B's tangential speed relative to A toward the difference of the two surfaces, within 1e5 m/s on every axis. Journaled; state, hashed when nonzero. A stale or null id, a refused value, or a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.shape: The shape.velocity: The surface velocity, m/s, world frame.Thread safety. Safe from any thread; a world is used by one thread at a time.
softbody.hSoft bodies: XPBD particle lattices bound by distance constraints and solved in a fixed index order each substep. Rope, cloth and jelly come from one factory. Ids are pooled, operations journaled and state snapshotted and hashed, so rollback covers them exactly.
m3SoftBodyDef m3DefaultSoftBodyDef(void);
Returns a soft body def with the defaults: a 4 x 4 x 4 lattice at 0.25 m spacing, 0.1 kg particles of radius 0.05 m, rigid rods, gravity scale 1, and no bend tethers, pressure or bind-pose tether, at the origin.
Returns: The def, with the cookie the creates check.
Thread safety. Safe from any thread.
M3_NODISCARD M3_API m3Result m3CreateSoftBody(m3World* world, const m3SoftBodyDef* def, m3SoftBodyId* softBodyOut);
Creates the lattice with structural edges and face diagonals in fixed index order, leaving *softBodyOut the null id on any refusal. Journaled with id verification.
Parameters:
world: The world.def: The def, from m3DefaultSoftBodyDef.softBodyOut: Receives the new id; any failure leaves the null id there when it is not null.Returns: m3_success; m3_errorInvalid for a null world, def or softBodyOut, a def m3DefaultSoftBodyDef did not make, an axis count below 1, a NaN position or gravity scale, a spacing, particle mass or radius that is not positive or is NaN, a compliance, bendCompliance or maxDeviation that is not finite or is negative, a pressure that is negative or NaN, or pressure on a lattice with an axis count below 2; m3_errorLimit for more than M3_MAX_SOFTBODY_PARTICLES particles or M3_MAX_SOFTBODY_EDGES edges, a particle mass outside M3_MIN_MASS to M3_MASS_LIMIT, a radius or spacing past M3_LOCAL_LIMIT, a gravity scale past M3_RATIO_LIMIT, a pressure past M3_SOFTBODY_PRESSURE_LIMIT, or a particle past M3_POSITION_LIMIT on any axis, infinities included; m3_errorCapacity for a full pool; m3_errorBusy from host code the world is running. Every refusal but a full pool's and a null world's counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3CreateTetSoftBody(m3World* world, const m3SoftBodyDef* def, const m3Vec3* points, int32_t pointCount, const uint16_t* tets, int32_t tetCount, m3SoftBodyId* softBodyOut);
A tetrahedral soft body: explicit points (world positions after adding def->position; each point within M3_LOCAL_LIMIT, 1e4 m, of def->position and each world position within 1e15 m on every axis, or m3_errorLimit) and tets (four point indices each, positive volume required). Edges come from the tet edges, deduplicated in first-touch order, at def->compliance; every tet holds its create volume rigidly (the incompressible jelly). The lattice's own fields do not apply: def->bendCompliance and def->pressure must be 0, or the create returns m3_errorInvalid, and def->countX/Y/Z and def->spacing are not read, so any value is accepted. Pins, anchors, wind, water, explosions, and collision all treat the particles exactly like lattice particles. Its refusals are listed below.
Parameters:
world: The world.def: The def, from m3DefaultSoftBodyDef, with the lattice fields at their defaults.points: The points, relative to def->position.pointCount: The number of points, 4 to M3_MAX_SOFTBODY_PARTICLES.tets: Four point indices per tet.tetCount: The number of tets, 1 to M3_MAX_SOFTBODY_TETS.softBodyOut: Receives the new id; any failure leaves the null id there when it is not null.Returns: m3_success; m3_errorInvalid for a null world, def, points, tets or softBodyOut, a def m3DefaultSoftBodyDef did not make, a nonzero bendCompliance or pressure, a NaN position, point or gravity scale, a compliance or maxDeviation that is not finite or is negative, a particle mass or radius that is not positive or is NaN, too few points or tets, or a tet that names a point out of range or twice or has no positive volume; m3_errorLimit for more than M3_MAX_SOFTBODY_PARTICLES points, M3_MAX_SOFTBODY_TETS tets or M3_MAX_SOFTBODY_EDGES edges, a point or position past its bound above, or a particle mass, radius or gravity scale past its bound, infinities included; m3_errorCapacity for a full pool; m3_errorBusy from host code the world is running. Every refusal but a full pool's and a null world's counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3DestroySoftBody(m3World* world, m3SoftBodyId softBody);
Destroys a soft body; its anchors and the soft pins that name it go with it. Journaled.
Parameters:
world: The world.softBody: The soft body.Returns: m3_success; m3_errorInvalid for a null world or the null id; m3_errorStale for an id whose soft body is gone; m3_errorBusy from host code the world is running. Each refusal but a null world's counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time.
bool m3SoftBody_IsValid(const m3World* world, m3SoftBodyId softBody);
Returns whether the id names a live soft body of this world.
Parameters:
world: The world; null gives false.softBody: The id.Returns: Whether the soft body is alive.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
M3_NODISCARD M3_API m3Result m3SoftBody_PinParticle(m3World* world, m3SoftBodyId softBody, int32_t particle);
Pins one particle in place (inverse mass zero): how a rope hangs and a flag flies. Journaled. Returns m3_success, or m3_errorStale for a stale id, m3_errorInvalid for the null id or an out-of-range particle and m3_errorBusy inside a step callback, which change nothing and count one misuse. Particle index is x + countX * (y + countY * z).
Parameters:
world: The world.softBody: The soft body.particle: The particle index, 0 to the particle count - 1.Returns: m3_success, or one of the refusals above.
Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3SoftBody_AnchorParticle(m3World* world, m3SoftBodyId softBody, int32_t particle, m3BodyId body);
Anchors one particle to a body at the particle's CURRENT position, expressed in the body's frame: the particle rides the body from then on, and the lattice's pull on it lands on the body as an impulse at the anchor, so the coupling is two-way. Cloth hangs from beams and jelly rides trucks through this. Anchoring to a static body is a moving pin; the anchor RELEASES silently if its body dies. Journaled. Returns m3_success; m3_errorLimit for a full anchor table (M3_MAX_SOFTBODY_ANCHORS per soft body), which changes nothing and counts no misuse; m3_errorStale for a stale id, m3_errorInvalid for the null id or an out-of-range particle and m3_errorBusy inside a step callback, which change nothing and count one misuse.
Parameters:
world: The world.softBody: The soft body.particle: The particle index, 0 to the particle count - 1.body: The body the particle rides; a stale one returns m3_errorStale and the null id m3_errorInvalid, each counting one misuse.Returns: m3_success, or one of the refusals above.
Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3SoftBody_AnchorToSoftBody(m3World* world, m3SoftBodyId softBodyA, int32_t particleA, m3SoftBodyId softBodyB, int32_t particleB);
Pin a particle of one lattice to a particle of ANOTHER lattice: a position equality split by inverse mass, solved each substep after soft-vs-soft contact. Released silently when EITHER lattice dies. Journaled; the pin lives in the lower slot's table (one canonical home per pair), which holds M3_MAX_SOFTBODY_ANCHORS. Returns m3_success; m3_errorLimit for a full table, which changes nothing and counts no misuse; m3_errorStale for a stale id, m3_errorInvalid for the null id, the same lattice twice or an out-of-range particle and m3_errorBusy inside a step callback, which change nothing and count one misuse.
Parameters:
world: The world.softBodyA: The first soft body.particleA: The first soft body's particle index.softBodyB: The second soft body, not softBodyA.particleB: The second soft body's particle index.Returns: m3_success, or one of the refusals above.
Thread safety. Safe from any thread; a world is used by one thread at a time.
int32_t m3SoftBody_GetParticleCount(const m3World* world, m3SoftBodyId softBody);
Returns how many particles a soft body has.
Parameters:
world: The world.softBody: The soft body.Returns: The particle count; 0 for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
m3Pos3 m3SoftBody_GetParticlePosition(const m3World* world, m3SoftBodyId softBody, int32_t particle);
Returns one particle's position.
Parameters:
world: The world.softBody: The soft body.particle: The particle index, 0 to the particle count - 1.Returns: The position; the origin for a null world, and for a stale or null id or an out-of-range particle, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
vehicle.hRaycast vehicles: each wheel is a suspension ray from the chassis with a spring and damper at the contact and tire friction in the contact plane. Vehicles are stepped inside m3World_Step in slot order and fully snapshotted, so a replayed or rolled-back drive lands on identical bits.
m3VehicleDef m3DefaultVehicleDef(void);
Returns a vehicle def with the defaults: no chassis and no wheels yet, every wheel slot hanging down 0.4 m with 0.25 m of travel at 1.5 Hz and a 0.6 damping ratio, a 0.3 m radius and a 0.25 brake share; a 0.6 rad steer, 800 N of drive, 1600 N of brake, a grip of 1.5 and no lean stabilization.
Returns: The def, with the cookie m3CreateVehicle checks.
Thread safety. Safe from any thread.
M3_NODISCARD M3_API m3Result m3CreateVehicle(m3World* world, const m3VehicleDef* def, m3VehicleId* vehicleOut);
Creates the vehicle bound to its chassis body. Refuses (null id) a non-dynamic or stale chassis, a wheel count outside [1, M3_MAX_VEHICLE_WHEELS], or any non-finite or non-positive geometry. Each wheel's anchor, rest length and radius lie within 1e4 m, its radius at least 1e-3 m, its hertz within 1e5 and its damping ratio and brake share within 1e4; drive and brake force within 1e20 N, tire grip and lean stabilization within 1e4. A value past one of these bounds, or a wheel count past M3_MAX_VEHICLE_WHEELS, returns m3_errorLimit; any other bad field m3_errorInvalid. Journaled with id verification.
Parameters:
world: The world.def: The def, from m3DefaultVehicleDef.vehicleOut: Receives the new id; any failure leaves the null id there when it is not null.Returns: m3_success; m3_errorInvalid for a null world, def or vehicleOut, a def m3DefaultVehicleDef did not make, a chassis that is stale, null or not dynamic, a wheel count below 1, a steer angle that is not finite or is negative, a drive force, brake force, tire grip or lean stabilization that is negative or NaN, or a wheel whose direction is not finite or not within 10 percent of unit length, whose travel is not positive or exceeds its rest length, whose anchor is NaN, whose rest length, hertz or radius is not positive or is NaN, or whose damping ratio or brake share is negative or NaN; m3_errorLimit for a wheel count past M3_MAX_VEHICLE_WHEELS, a drive or brake force past 1e20 N, a tire grip or lean stabilization past 1e4, or a wheel anchor, rest length or radius past 1e4 m, a radius below 1e-3 m, a hertz past 1e5 or a damping ratio or brake share past 1e4, infinities included; m3_errorCapacity when the vehicle pool is full; m3_errorBusy from host code the world is running. Every refusal but a full pool's and a null world's counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3DestroyVehicle(m3World* world, m3VehicleId vehicle);
Destroys a vehicle; its chassis body stays. Journaled.
Parameters:
world: The world.vehicle: The vehicle.Returns: m3_success; m3_errorInvalid for a null world or the null id; m3_errorStale for an id whose vehicle is gone; m3_errorBusy from host code the world is running. Each refusal but a null world's counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time.
bool m3Vehicle_IsValid(const m3World* world, m3VehicleId vehicle);
Returns whether the id names a live vehicle of this world.
Parameters:
world: The world; null gives false.vehicle: The id.Returns: Whether the vehicle is alive.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
float m3Vehicle_GetWheelCompression(const m3World* world, m3VehicleId vehicle, int32_t wheel);
Last step's suspension compression of one wheel, in meters from rest length (zero when airborne, stale, or out of range). Frozen while the chassis sleeps, like the chassis.
Parameters:
world: The world.vehicle: The vehicle.wheel: The wheel index, 0 to the wheel count - 1.Returns: The compression in meters; 0 while airborne, for a null world, and for a stale or null id or an out-of-range wheel, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
bool m3Vehicle_IsWheelGrounded(const m3World* world, m3VehicleId vehicle, int32_t wheel);
Whether the wheel's suspension cast found ground last step.
Parameters:
world: The world.vehicle: The vehicle.wheel: The wheel index, 0 to the wheel count - 1.Returns: Whether it touched ground; false for a null world, and for a stale or null id or an out-of-range wheel, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3Vehicle_SetTankCommands(m3World* world, m3VehicleId vehicle, float left, float right, float brake);
Drive commands: journaled STATE, not per-step parameters, so replay and rollback hold to the bit. Values clamp to their ranges (throttle and steer to [-1, 1], brake to [0, 1]); non-finite commands are hostile no-ops that never journal. Setting commands wakes the chassis. The chassis-local +x axis is the vehicle's forward by convention; steer rotates each steerable wheel's frame about its suspension axis by steer * maxSteerAngle. Tank commands: per-side throttle for skid steering. Driven wheels split by the sign of their chassis-local anchor z (+z right); each side takes its own throttle in [-1, 1], the brake rides all wheels. Engaging tank mode suspends the normal throttle until m3Vehicle_SetCommands is called again (which disengages it). Drivetrain vehicles refuse: a gearbox and a skid steer are different machines.
A refused call changes nothing, is not journaled and counts one misuse: a stale or null id, a non-finite command, a drivetrain vehicle, or a call from host code the world is running.
Parameters:
world: The world.vehicle: The vehicle.left: The left side's throttle, clamped to [-1, 1].right: The right side's throttle, clamped to [-1, 1].brake: The brake, clamped to [0, 1].Thread safety. Safe from any thread; a world is used by one thread at a time.
void m3Vehicle_SetCommands(m3World* world, m3VehicleId vehicle, float throttle, float steer, float brake);
Sets the drive commands, as described above, and leaves tank mode. A refused call changes nothing, is not journaled and counts one misuse: a stale or null id, a non-finite command, or a call from host code the world is running.
Parameters:
world: The world.vehicle: The vehicle.throttle: The throttle, clamped to [-1, 1].steer: The steer, clamped to [-1, 1].brake: The brake, clamped to [0, 1].Thread safety. Safe from any thread; a world is used by one thread at a time.
float m3Vehicle_GetWheelSpin(const m3World* world, m3VehicleId vehicle, int32_t wheel);
Accumulated spin angle of one wheel in radians (rendering state: hosts spin their wheel meshes with it).
Parameters:
world: The world.vehicle: The vehicle.wheel: The wheel index, 0 to the wheel count - 1.Returns: The spin angle in radians; 0 for a null world, and for a stale or null id or an out-of-range wheel, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
m3DrivetrainDef m3DefaultDrivetrainDef(void);
Returns a drivetrain def for a plain small car: a four-point curve from 120 N m at 1000 rpm to a 200 N m peak at 3000 rpm, five gears from 3.5 to 0.9, a 3.2 reverse, a 3.7 final drive, automatic shifts at 5500 and 2000 rpm with 12 clutch steps, and an open differential.
Returns: The def, with the cookie m3Vehicle_SetDrivetrain checks.
Thread safety. Safe from any thread.
void m3Vehicle_SetDrivetrain(m3World* world, m3VehicleId vehicle, const m3DrivetrainDef* def);
Attach a drivetrain (journaled). Replaces the flat driveForce model for this vehicle; starts in first gear, clutch closed. Invalid defs are documented no-ops: a def m3DefaultDrivetrainDef did not make, a curve count outside 2 to M3_MAX_DRIVETRAIN_CURVE_POINTS, a gear count outside 1 to M3_MAX_DRIVETRAIN_GEARS, clutch steps outside 0 to M3_MAX_CLUTCH_STEPS, a curve rpm that is not finite, is negative or does not ascend strictly, a torque that is negative, NaN or past 1e20 N m, a gear ratio or final drive that is not positive, is NaN or is past 1e4, a reverse ratio that is negative, NaN or past 1e4, a shift rpm that is not finite, a negative shift-down rpm or a shift-up rpm not above it, a differential mode out of range, or a coupling that is negative, NaN or past 1e15.
Parameters:
world: The world.vehicle: The vehicle; a stale or null id is a no-op that counts one misuse.def: The def, from m3DefaultDrivetrainDef. A null or invalid def is a no-op that is not journaled and counts one misuse, as is a call from host code the world is running.Thread safety. Safe from any thread; a world is used by one thread at a time.
void m3Vehicle_SetGear(m3World* world, m3VehicleId vehicle, int32_t gear);
Select a gear (journaled): -1 reverse, 0 neutral, 1..gearCount. Opens the clutch for clutchSteps. A no-op without a drivetrain, out of range, or when reverseRatio is zero and gear is -1.
Parameters:
world: The world.vehicle: The vehicle; a stale or null id is a no-op.gear: The gear: -1 reverse, 0 neutral, 1 to gearCount. Each no-op is not journaled and counts one misuse, as does a call from host code the world is running.Thread safety. Safe from any thread; a world is used by one thread at a time.
int32_t m3Vehicle_GetGear(const m3World* world, m3VehicleId vehicle);
Current gear; 0 when no drivetrain is attached.
Parameters:
world: The world.vehicle: The vehicle.Returns: The gear; 0 without a drivetrain, for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
float m3Vehicle_GetEngineRpm(const m3World* world, m3VehicleId vehicle);
Engine speed computed by the last step, idle-floored like the torque lookup (a tachometer, not raw wheel math).
Parameters:
world: The world.vehicle: The vehicle.Returns: The engine speed in rpm; 0 without a drivetrain, for a null world, and for a stale or null id, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
world.hThe world: creation, stepping, tuning, snapshots, the command journal, queries, explosions, counters and diagnostics.
m3QueryFilter m3DefaultQueryFilter(void);
Returns the filter that sees every shape: every category and mask bit set.
Returns: The filter.
Thread safety. Safe from any thread.
m3WorldDef m3DefaultWorldDefValues(void);
The library's world defaults: gravity (0, -10, 0), 1024 bodies, 2048 shapes, 64 joints, 4 meshes, 4 voxel chunks, 4 characters, 2 vehicles, no task hooks, the C library's allocator, and the def cookie, with version left 0. Call m3DefaultWorldDef instead, which stamps the version of the program's headers.
Returns: The defaults, with version 0.
Thread safety. Safe from any thread.
static inline m3WorldDef m3DefaultWorldDef(void);
The world defaults, stamped with M3_ABI_VERSION of the headers the program is built with, so m3CreateWorld can refuse a def made for another minor version's binary interface.
M3_NODISCARD M3_API m3Result m3CreateWorld(const m3WorldDef* def, m3World** worldOut);
Creates a world. The checks run in order: a null worldOut, then the CPU, which must run the library's SIMD backend, then the def's cookie, its version and the rest of its fields. A def whose step scratch, sized at its capacities, would pass 2 GiB is refused before anything is allocated; when the allocator refuses, nothing is left allocated. The world takes the scratch a step needs here, about 918 bytes per pair of pairCapacity, 126 per body and 416 per joint on a 64-bit target (m3MemoryUsage.scratchCapacity), so no step asks the allocator. *worldOut is null on any failure. No world exists yet, so no refusal counts misuse.
Parameters:
def: The def, from m3DefaultWorldDef.worldOut: Receives the new world.Returns: m3_success; m3_errorUnsupported for a CPU that cannot run the library's SIMD backend; m3_errorInvalid for a null def or worldOut, a def m3DefaultWorldDef did not make, a body, shape, mesh, joint, voxel, character, vehicle or soft body capacity of 0 or less, a negative pairCapacity, only one of enqueueTask and finishTask, an allocator with only one of alloc and free, a restitution or hit event threshold that is negative or not finite, a NaN gravity component, or a contact hertz, damping ratio, push speed or maximum linear or angular speed that is not positive or is NaN; m3_errorVersion for a def version other than M3_ABI_VERSION; m3_errorLimit for a shapeCapacity past M3_MAX_SHAPE_CAPACITY, a pairCapacity past M3_MAX_PAIR_CAPACITY, a voxelCapacity past M3_MAX_VOXEL_CAPACITY, a gravity component past M3_ACCEL_LIMIT, a contact hertz past M3_HERTZ_LIMIT, a damping ratio past M3_RATIO_LIMIT, or a push speed or speed cap past M3_SPEED_LIMIT, infinities included; m3_errorCapacity for a step scratch past 2 GiB or an allocator that refuses the world.
Thread safety. Safe from any thread; def's allocator is used by one thread at a time.
void m3DestroyWorld(m3World* world);
Destroys a world and everything it owns; ids it issued mean nothing after. Null is a no-op. Called from host code the world is running, it destroys nothing and counts one misuse.
Parameters:
world: The world.Thread safety. Safe from any thread; a world is used by one thread at a time.
void m3World_SetGravity(m3World* world, m3Vec3 gravity);
Set the gravity vector, within 1e4 m/s^2 on every axis. Journaled; sleeping islands stay asleep until disturbed. A null world does nothing. A NaN gravity component, or one past 1e4 m/s^2 or infinite, or a call from host code the world is running, changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.gravity: The gravity, m/s^2, within 1e4 on every axis.Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3World_RebuildBroadphase(m3World* world);
Rebuild the broadphase tree top down, balanced. Bulk shape creation grows the tree one insertion at a time and can leave it lopsided; call this once after building a level and queries walk a balanced tree instead. Deterministic and journaled: the rebuilt shape is a pure function of the live shapes, so twins and replays agree. Returns m3_errorCapacity, with the tree unchanged and nothing recorded, when the world's allocator refuses the scratch.
Parameters:
world: The world.Returns: m3_success; m3_errorCapacity as above; m3_errorInvalid for a null world; m3_errorBusy from host code the world is running, which counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time.
m3WaterVolumeDef m3DefaultWaterVolumeDef(void);
Returns a water volume def with the defaults: the unit box at the origin, density 1000, linear drag 2, angular drag 1 and no flow.
Returns: The def, with the cookie m3CreateWaterVolume checks.
Thread safety. Safe from any thread.
M3_NODISCARD M3_API m3Result m3CreateWaterVolume(m3World* world, const m3WaterVolumeDef* def, m3WaterVolumeId* volumeOut);
Creates a water volume. A box past M3_POSITION_LIMIT, a density past M3_DENSITY_LIMIT or a flow past M3_SPEED_LIMIT returns m3_errorLimit, any other bad field m3_errorInvalid. Up to M3_MAX_WATER_VOLUMES per world; journaled, snapshotted, hashed off-default. Creating or destroying a volume wakes every body whose bounds touch it (the tide moves things).
Parameters:
world: The world.def: The def, from m3DefaultWaterVolumeDef.volumeOut: Receives the new id; any failure leaves the null id there when it is not null.Returns: m3_success; m3_errorInvalid for a null world, def or volumeOut, a def m3DefaultWaterVolumeDef did not make, a box that is empty or inverted on an axis, a NaN bound or flow, a density that is not positive or is NaN, or a drag that is not finite or is negative; m3_errorLimit as above, infinities included; m3_errorCapacity past M3_MAX_WATER_VOLUMES; m3_errorBusy from host code the world is running. Every refusal but a full table's and a null world's counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3DestroyWaterVolume(m3World* world, m3WaterVolumeId volume);
Destroys a water volume, waking the bodies it touches. Journaled.
Parameters:
world: The world.volume: The volume.Returns: m3_success; m3_errorInvalid for a null world or the null id; m3_errorStale for a gone volume; m3_errorBusy from host code the world is running. Each refusal but a null world's counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time.
bool m3WaterVolume_IsValid(const m3World* world, m3WaterVolumeId volume);
Returns whether the id names a live water volume of this world.
Parameters:
world: The world; null gives false.volume: The id.Returns: Whether the volume is alive.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
m3Vec3 m3World_GetGravity(const m3World* world);
Current gravity.
Parameters:
world: The world.Returns: The gravity, m/s^2; zero for a null world.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3World_SetContactTuning(m3World* world, float hertz, float dampingRatio, float pushMaxSpeed);
Contact softness tuning: frequency (hertz, up to 1e5), damping ratio (up to 1e4) and the maximum depenetration speed (up to 1e5 m/s), each positive. Journaled. Static contacts use twice the frequency: a soft row against something immovable stores energy under a tall stack. A null world does nothing. A hertz, damping ratio or push speed that is not positive or is NaN, or past 1e5, 1e4 or 1e5 or infinite, or a call from host code the world is running, changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.hertz: The contact frequency, hertz.dampingRatio: The contact damping ratio.pushMaxSpeed: The maximum depenetration speed, m/s.Thread safety. Safe from any thread; a world is used by one thread at a time.
void m3World_SetRestitutionThreshold(m3World* world, float value);
Impact speed below the threshold does not bounce. Journaled. A null world does nothing. A negative or non-finite threshold, or a call from host code the world is running, changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.value: The threshold, m/s, finite and not negative.Thread safety. Safe from any thread; a world is used by one thread at a time.
void m3World_SetMaximumLinearSpeed(m3World* world, float value);
Hard cap on any body's linear speed, applied every substep: positive and at most 1e5 m/s, the speed the step holds every body within. Journaled. A null world does nothing. A cap that is not positive or is NaN, or past 1e5 or infinite, or a call from host code the world is running, changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.value: The cap, m/s.Thread safety. Safe from any thread; a world is used by one thread at a time.
void m3World_SetMaximumAngularSpeed(m3World* world, float value);
Hard cap on any body's angular speed in rad/s, applied every substep. The default (800) is a catastrophe guard, not a gameplay clamp; bodies flagged with m3Body_EnableFastRotation bypass it. Positive and at most 1e5 rad/s; the step holds every body, flagged or not, within 1e5 rad/s. Journaled. A null world does nothing. A cap that is not positive or is NaN, or past 1e5 or infinite, or a call from host code the world is running, changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.value: The cap, rad/s.Thread safety. Safe from any thread; a world is used by one thread at a time.
void m3World_EnableSleep(m3World* world, bool flag);
Turn island sleeping on or off. Turning it OFF wakes every sleeping body. Journaled. A null world does nothing; a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.flag: Whether islands may sleep.Thread safety. Safe from any thread; a world is used by one thread at a time.
bool m3World_IsSleepEnabled(const m3World* world);
Whether island sleeping is enabled.
Parameters:
world: The world.Returns: Whether it is; false for a null world.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3World_EnableContinuous(m3World* world, bool flag);
Turn the continuous phase (CCD) on or off. Journaled. A null world does nothing; a call from host code the world is running changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.flag: Whether the continuous phase runs.Thread safety. Safe from any thread; a world is used by one thread at a time.
bool m3World_IsContinuousEnabled(const m3World* world);
Whether the continuous phase is enabled.
Parameters:
world: The world.Returns: Whether it is; false for a null world.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3World_SetWind(m3World* world, m3Vec3 direction, float speed, float gustHertz, float gustScale);
Wind: a deterministic field applied to soft-body particles as proportional drag toward the wind velocity. The gust is a sine of an ACCUMULATED phase (state, in the snapshot), so rollbacks resume the exact same wave: no host randomness exists anywhere in it. speed zero disables. direction must be near-unit when speed is nonzero; speed is within 1e5 m/s, gustHertz within 1e5 and gustScale within 1e4, each non-negative, on the call and on replay alike. The wind blows soft particles only; push rigid bodies with forces. Journaled. A null world does nothing. A non-finite direction, a negative or NaN speed, gust frequency or gust scale, one past 1e5, 1e5 or 1e4 or infinite, or a direction whose squared length is outside [0.99, 1.01] while the speed is not zero, or a call from host code the world is running, changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.direction: The wind's direction, near unit.speed: The wind speed, m/s; 0 disables.gustHertz: The gust frequency, hertz.gustScale: The gust's share of the speed.Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3World_Step(m3World* world, float dt, int32_t substepCount);
Advance the simulation: collide, then the Soft Step solver with the given substep count (1..256) over dt, 1e-4 to 10 seconds; out of range refuses loudly. Deterministic: same inputs, same bits, on every platform and backend. Journaled. THE THREADING CONTRACT. Per world: one writer at a time; Step and every mutating call demand exclusive access to that world. Between steps, any number of concurrent READERS (queries, casts, getters, snapshot) may run on the same world from any threads. DISTINCT worlds are fully independent: stepping two worlds on two host threads is supported and bit-identical to stepping them serially (the concurrency suite proves it; the TSAN cell polices it). The library keeps no process-wide state, so worlds may be created and destroyed on any threads at once. Reading a world WHILE it steps is undefined.
A step never asks the allocator: the world took the scratch a step needs at its capacities when it was created. Returns m3_errorInvalid for a NULL world, a NaN dt, a dt of zero or below or fewer than one substep, m3_errorLimit for a dt below M3_MIN_STEP or above M3_STEP_LIMIT, an infinite one included, or more than M3_MAX_SUBSTEPS substeps, and m3_errorBusy when called from host code the world is running; each changes nothing. A step that finds more broadphase pairs than m3WorldDef.pairCapacity holds still runs whole and returns m3_success: it keeps the pairs of the lowest shape indexes, and the shapes of each pair it drops get no contact that step and pass through each other. m3Counters.pairsDropped counts the drops.
Parameters:
world: The world.dt: The step, seconds.substepCount: The solver substeps, 1 to M3_MAX_SUBSTEPS.Returns: m3_success, or one of the refusals above, each counting one misuse but a null world's.
Thread safety. Safe from any thread; a world is used by one thread at a time.
int64_t m3World_GetSnapshotSize(const m3World* world);
Snapshot and rollback, first-class from day one. The format is portable and versioned: field blocks in little-endian order, laid out the same on every target, after a header carrying the state prefix (the writing release's M3_ABI_VERSION and the format's number), a config hash (solver revision, precision, FP policy) and the world's capacities. Only the releases of the minor version that wrote a snapshot read it: restore refuses another minor version, format or config with m3_errorVersion and another world shape with m3_errorFormat, restores in place, and the restored world resimulates bit-exactly. Before any byte lands, every block is checked: out-of-range indices and counts, flags that are not flags, and non-finite state refuse with m3_errorFormat and leave the world as it was. Then the structures are checked as wholes: restore refuses, the same way, any snapshot whose links, lists, pools, trees or per-record values this engine could not have written (id pools, body to shape and joint lists, the broadphase tree, the contact pairs, shared content and its reference counts, and the records of characters, vehicles, soft bodies and joints), and any value past the limit its create or setter keeps (the magnitude limits of docs/user/limits.md), positions included: creates place every body and soft particle within 1e15 m and the step holds it there. Replay and restore take a shape's geometry only in the form its create leaves it. Mass, center, inertia and extents are not stored; restore rebuilds them from each body's type and shapes. A world restore accepts steps, queries and snapshots like one the API built. Snapshot writes m3World_GetSnapshotSize bytes and sets bytesOut; a smaller buffer returns m3_errorCapacity. Any failure, a null world's included, leaves bytesOut zero and zeroes the buffer over its whole capacity, so no part of a refused snapshot reads as a valid one; a host that rings snapshot buffers sizes each with m3World_GetSnapshotSize first. Sizes are 64-bit and have no cap of their own: a world that fits memory snapshots. On a 32-bit target Restore refuses a size past SIZE_MAX with m3_errorInvalid before it forms a pointer.
Parameters:
world: The world.Returns: The snapshot's size in bytes; -1 for a null world.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
M3_NODISCARD M3_API m3Result m3World_Snapshot(const m3World* world, void* buffer, int64_t capacity, int64_t* bytesOut);
Writes the world's snapshot, as described above.
Parameters:
world: The world.buffer: Receives the snapshot.capacity: buffer's length in bytes.bytesOut: Receives the snapshot's length.Returns: m3_success; m3_errorInvalid for a null world, buffer or bytesOut; m3_errorCapacity for a buffer smaller than m3World_GetSnapshotSize. Each refusal but a null world's counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
M3_NODISCARD M3_API m3Result m3World_Restore(m3World* world, const void* data, int64_t size);
Restores a snapshot into this world in place, as described above.
Parameters:
world: The world.data: The snapshot, as m3World_Snapshot wrote it.size: The snapshot's length in bytes.Returns: m3_success; m3_errorInvalid for a null world, a negative size, one this target cannot address, or null data with a positive size; m3_errorVersion or m3_errorFormat as above, which count no misuse; m3_errorCapacity, counting no misuse, for an allocator that refuses the scratch the checks take or the staged content; m3_errorBusy from host code the world is running. A refusal leaves the world as it was, and the invalid and busy refusals count one misuse but a null world's.
Thread safety. Safe from any thread; a world is used by one thread at a time.
m3ContactEvents m3World_GetContactEvents(const m3World* world);
Returns the last step's contact events.
Parameters:
world: The world.Returns: The streams, owned by the world; empty for a null world.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
m3SensorEvents m3World_GetSensorEvents(const m3World* world);
Returns the last step's sensor events.
Parameters:
world: The world.Returns: The streams, owned by the world; empty for a null world.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
m3FragmentEvents m3World_GetFragmentEvents(const m3World* world);
Returns the last step's fragment events.
Parameters:
world: The world.Returns: The streams, owned by the world; empty for a null world.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3World_SetHitEventThreshold(m3World* world, float value);
Hit events require approach speed above this. Journaled. A null world does nothing. A negative or non-finite threshold, or a call from host code the world is running, changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.value: The threshold, m/s, finite and not negative.Thread safety. Safe from any thread; a world is used by one thread at a time.
m3BodyEvents m3World_GetBodyEvents(const m3World* world);
Returns the last step's body move events.
Parameters:
world: The world.Returns: The streams, owned by the world; empty for a null world.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
m3JointEvents m3World_GetJointEvents(const m3World* world);
Returns the last step's joint break events.
Parameters:
world: The world.Returns: The streams, owned by the world; empty for a null world.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
void m3World_SetPreSolveCallback(m3World* world, m3PreSolveFunction* fn, void* context);
Register (or clear with NULL) the pre-solve callback. The REGISTRATION is host wiring (never journaled, never snapshot state), but the DECISIONS are not: every veto a step makes is journaled as that step's annex, so a replay (m3replay verify included) applies each step's recorded vetoes, none for a step that recorded none, and lands on the recorded bits. A replay never calls the callback, installed or not; do not expect callbacks to fire under replay. A null world does nothing; a call from host code the world is running changes nothing and counts one misuse.
Parameters:
world: The world.fn: The callback, or null to clear it.context: Passed to every call of fn.Thread safety. Safe from any thread; a world is used by one thread at a time.
bool m3World_CastMover(const m3World* world, m3Pos3 center, float halfHeight, float radius, m3Vec3 translation, m3CastHit* hitOut);
Cast the mover capsule along a translation; the closest blocking hit (sensors are invisible to movers), with the closest casts' contract below.
Parameters:
world: The world.center: The capsule's center.halfHeight: Half the distance between the cap centers, not negative.radius: The capsule's radius.translation: The move to cast along.hitOut: Receives the closest hit.Returns: Whether the capsule hits a shape. hitOut is cleared first and holds the hit only on true. A null hitOut, or a null world, a center that is not finite, a half height that is negative or not finite, a radius that is not finite or not positive, or a translation that is NaN or past M3_CAST_LIMIT on an axis, is refused: it returns false and counts one misuse, but a null world counts none.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
int32_t m3World_CollideMover(const m3World* world, m3Pos3 center, float halfHeight, float radius, float skin, m3MoverPlane* planesOut, int32_t capacity);
Collect contact planes for the mover at rest: every shape within skin of the capsule contributes one plane, the lowest shape indexes first in ascending order. Like every list call it writes at most capacity entries and returns the total, which may exceed capacity; a NULL array with capacity 0 measures. A refused list call returns 0 and zeroes the array over its whole capacity, so no entry of an earlier call is read as the answer, and zeroed ids are null ids; a successful answer, an empty one included, writes only its entries and leaves the rest of the array as it was. A list call only reads, so none is refused as busy. Pass the smaller of the two to m3SolveMover.
Parameters:
world: The world.center: The capsule's center.halfHeight: Half the distance between the cap centers.radius: The capsule's radius.skin: How far from the capsule a shape still counts.planesOut: Receives up to capacity planes.capacity: planesOut's length, at least 0.Returns: The total number of planes; 0 on a refusal, which zeroes the array over its capacity and counts one misuse but a null world's: a null world, a negative capacity or a null array with a positive one, a center that is not finite, a half height or skin that is negative or not finite, or a radius that is not finite or not positive.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
m3MoverMove m3SolveMover(m3Vec3 wish, const m3MoverPlane* planes, int32_t count);
The closest translation to the wish that no plane blocks, and the planes it rests on. Pure function, world-free. Only the first M3_MAX_MOVER_PLANES planes take part.
Parameters:
wish: The wanted translation.planes: The planes, as m3World_CollideMover wrote them.count: The number of planes.Returns: The move and its pressed planes; the wish unchanged with no plane pressed for a null planes, a count below 1 or a wish that is not finite. No world is involved, so nothing counts misuse.
Thread safety. Safe from any thread.
m3Vec3 m3ClipMoverVelocity(m3Vec3 velocity, const m3MoverPlane* planes, int32_t count, uint32_t pressed);
The velocity closest to the given one that no pressed plane opposes: what is left after hitting them. Pure function.
Parameters:
velocity: The velocity to clip.planes: The planes m3SolveMover saw.count: The number of planes.pressed: m3MoverMove.pressed from that solve.Returns: The clipped velocity; velocity unchanged for a null planes, a count below 1, a velocity that is not finite, or no pressed bit below both count and M3_MAX_MOVER_PLANES.
Thread safety. Safe from any thread.
bool m3World_CastRayClosest(const m3World* world, m3Pos3 origin, m3Vec3 translation, m3QueryFilter filter, m3CastHit* hitOut);
Every query takes an m3QueryFilter and sees the shapes a shape with those bits would touch; m3DefaultQueryFilter sees them all. The closest front-face hit along origin + t * translation for t in [0, 1]: rays MISS shapes they start inside or exactly on (front faces only); ask m3World_TestPoint for containment. Every closest cast clears hitOut first, then returns true on a hit and writes it there, or returns false and leaves it zeroed: on a miss, and on a hostile input or a null world, which count one misuse. A null hitOut returns false and counts one misuse.
Parameters:
world: The world.origin: The ray's start.translation: The ray's direction times its reach.filter: The query filter; m3DefaultQueryFilter sees every shape.hitOut: Receives the closest hit.Returns: Whether the ray hits a shape. hitOut is cleared first and holds the hit only on true. A null hitOut, or a null world, an origin that is not finite or a translation that is NaN or past M3_CAST_LIMIT on an axis, is refused: it returns false and counts one misuse, but a null world counts none. A zero translation is a clean miss.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
int32_t m3World_CastRayAll(const m3World* world, m3Pos3 origin, m3Vec3 translation, m3QueryFilter filter, m3CastHit* hitsOut, int32_t capacity);
Every ray hit along the translation, one entry point per shape, sorted by fraction (ties to the lower shape index). It writes the nearest capacity hits and returns the total, which may exceed capacity; a NULL array with capacity 0 measures. A refusal zeroes the array over its whole capacity; a success, an empty one included, writes only its entries; a list call only reads, so none is refused as busy.
Parameters:
world: The world.origin: The ray's start.translation: The ray's direction times its reach.filter: The query filter; m3DefaultQueryFilter sees every shape.hitsOut: Receives up to capacity hits, nearest first.capacity: hitsOut's length, at least 0.Returns: The total number of hits found; 0 on a refusal, which zeroes the array over its capacity and counts one misuse but a null world's: a null world, a negative capacity or a null array with a positive one, an origin that is not finite, a zero translation, or a translation that is NaN or past M3_CAST_LIMIT on an axis.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
bool m3World_CastBoxClosest(const m3World* world, m3Pos3 center, m3Vec3 halfExtents, m3Quat rotation, m3Vec3 translation, m3QueryFilter filter, m3CastHit* hitOut);
Closest-hit shape casts: sweep a sphere or a capsule along a translation. fraction is the earliest touch in [0, 1]; a cast that STARTS overlapped hits at fraction zero with a zero normal (the documented start-inside contract; rays instead MISS shapes they start inside, front faces only). Generic convex casts: a box (with orientation) or a caller point cloud (2 to M3_MAX_CAST_POINTS points, base-relative) swept along a translation, skinless. Same contracts as every cast: the earliest touch in [0, 1], start-overlapped reports fraction zero with a zero normal, hostile inputs miss. A single point is a ray: use the ray casts.
Parameters:
world: The world.center: The box's center.halfExtents: The box's half extents, each positive.rotation: The box's rotation, a unit quaternion.translation: The sweep.filter: The query filter; m3DefaultQueryFilter sees every shape.hitOut: Receives the closest hit.Returns: Whether the box hits a shape. hitOut is cleared first and holds the hit only on true. A null hitOut, or a null world, a center or translation that is not finite, a half extent that is not finite or not positive, a rotation that is not finite or whose squared length is not within 2 percent of 1, or a translation that is NaN or past M3_CAST_LIMIT on an axis, is refused: it returns false and counts one misuse, but a null world counts none.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
bool m3World_CastHullClosest(const m3World* world, m3Pos3 base, const m3Vec3* points, int32_t count, m3Vec3 translation, m3QueryFilter filter, m3CastHit* hitOut);
Sweeps a point cloud's hull along a translation; see above.
Parameters:
world: The world.base: The point the cloud is relative to.points: The cloud, base-relative.count: The number of points, 2 to M3_MAX_CAST_POINTS.translation: The sweep.filter: The query filter; m3DefaultQueryFilter sees every shape.hitOut: Receives the closest hit.Returns: Whether the hull hits a shape. hitOut is cleared first and holds the hit only on true. A null hitOut, or a null world, null points, a count outside 2 to M3_MAX_CAST_POINTS, a base, point or translation that is not finite, or a translation that is NaN or past M3_CAST_LIMIT on an axis, is refused: it returns false and counts one misuse, but a null world counts none.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
bool m3World_CastSphereClosest(const m3World* world, m3Pos3 center, float radius, m3Vec3 translation, m3QueryFilter filter, m3CastHit* hitOut);
Sweeps a sphere along a translation; see above.
Parameters:
world: The world.center: The sphere's center.radius: The sphere's radius.translation: The sweep.filter: The query filter; m3DefaultQueryFilter sees every shape.hitOut: Receives the closest hit.Returns: Whether the sphere hits a shape. hitOut is cleared first and holds the hit only on true. A null hitOut, or a null world, a center that is not finite, a radius that is not finite or not positive, or a translation that is NaN or past M3_CAST_LIMIT on an axis, is refused: it returns false and counts one misuse, but a null world counts none.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
bool m3World_CastCapsuleClosest(const m3World* world, m3Pos3 center, m3Vec3 point1, m3Vec3 point2, float radius, m3Vec3 translation, m3QueryFilter filter, m3CastHit* hitOut);
Sweeps a capsule along a translation; see above.
Parameters:
world: The world.center: The capsule's center.point1: The first segment end, relative to center.point2: The second segment end, relative to center.radius: The capsule's radius.translation: The sweep.filter: The query filter; m3DefaultQueryFilter sees every shape.hitOut: Receives the closest hit.Returns: Whether the capsule hits a shape. hitOut is cleared first and holds the hit only on true. A null hitOut, or a null world, a center or point that is not finite, a radius that is not finite or is negative, or a translation that is NaN or past M3_CAST_LIMIT on an axis, is refused: it returns false and counts one misuse, but a null world counts none.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
m3ShapeId m3World_TestPoint(const m3World* world, m3Pos3 point, m3QueryFilter filter);
The first shape (lowest index) the filter sees whose volume contains the point, or the null id. A disabled body's shapes are skipped. Meshes are open surfaces and never contain points; planes are solid half spaces.
Parameters:
world: The world.point: The point.filter: The query filter; m3DefaultQueryFilter sees every shape.Returns: The shape's id; the null id when no shape holds the point, and for a null world or a point that is not finite, which counts one misuse but a null world's.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
int32_t m3World_OverlapAabb(const m3World* world, m3WorldAabb box, m3QueryFilter filter, m3ShapeId* idsOut, int32_t capacity);
The overlap queries write the lowest capacity shape ids in ascending shape index order and return the total, which may exceed capacity; a NULL array with capacity 0 measures. A NULL array with a positive capacity or a negative capacity refuses. A refusal zeroes the array over its whole capacity; a success, an empty one included, writes only its entries; a list call only reads, so none is refused as busy. Shapes whose tight bounds overlap the box. A box with a non-finite bound, or with its lower bound above its upper bound on any axis, is refused: the call returns 0, zeroes the array and counts one misuse. A flat or one-point box, lower equal to upper on an axis, is a valid query.
Parameters:
world: The world.box: The box.filter: The query filter; m3DefaultQueryFilter sees every shape.idsOut: Receives up to capacity shape ids, in ascending shape index order.capacity: idsOut's length, at least 0.Returns: The total number of shapes found; 0 on a refusal, which zeroes the array over its capacity and counts one misuse but a null world's: a null world, a negative capacity or a null array with a positive one, a bound that is not finite, or a lower bound above the upper bound on an axis.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
int32_t m3World_OverlapSphere(const m3World* world, m3Pos3 center, float radius, m3QueryFilter filter, m3ShapeId* idsOut, int32_t capacity);
Shapes within reach of the sphere (exact per family).
Parameters:
world: The world.center: The sphere's center.radius: The sphere's radius.filter: The query filter; m3DefaultQueryFilter sees every shape.idsOut: Receives up to capacity shape ids, in ascending shape index order.capacity: idsOut's length, at least 0.Returns: The total number of shapes found; 0 on a refusal, which zeroes the array over its capacity and counts one misuse but a null world's: a null world, a negative capacity or a null array with a positive one, a center that is not finite, or a radius that is not finite or not positive.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
int32_t m3World_OverlapCapsule(const m3World* world, m3Pos3 center, m3Vec3 point1, m3Vec3 point2, float radius, m3QueryFilter filter, m3ShapeId* idsOut, int32_t capacity);
The exact overlap family: capsule, oriented box, and raw convex cloud queries with the same contract as the sphere: shapes within EXACT reach (GJK per candidate, planes and voxel/mesh handled per family), ascending shape index, filtered, read-only. The capsule's two points are relative to its center. Clouds carry base-relative points (the cast convention), at most 64 of them. A box's rotation is within a percent of unit length, as the box cast's: any other refuses.
Parameters:
world: The world.center: The capsule's center.point1: The first segment end, relative to center.point2: The second segment end, relative to center.radius: The capsule's radius.filter: The query filter; m3DefaultQueryFilter sees every shape.idsOut: Receives up to capacity shape ids, in ascending shape index order.capacity: idsOut's length, at least 0.Returns: The total number of shapes found; 0 on a refusal, which zeroes the array over its capacity and counts one misuse but a null world's: a null world, a negative capacity or a null array with a positive one, a center or point that is not finite, or a radius that is not finite or is negative.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
int32_t m3World_OverlapBox(const m3World* world, m3Pos3 center, m3Vec3 halfExtents, m3Quat rotation, m3QueryFilter filter, m3ShapeId* idsOut, int32_t capacity);
Shapes within exact reach of an oriented box; see above.
Parameters:
world: The world.center: The box's center.halfExtents: The box's half extents, each positive.rotation: The box's rotation, a unit quaternion.filter: The query filter; m3DefaultQueryFilter sees every shape.idsOut: Receives up to capacity shape ids, in ascending shape index order.capacity: idsOut's length, at least 0.Returns: The total number of shapes found; 0 on a refusal, which zeroes the array over its capacity and counts one misuse but a null world's: a null world, a negative capacity or a null array with a positive one, a center that is not finite, a half extent that is not finite or not positive, or a rotation that is not finite or whose squared length is not within 2 percent of 1.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
int32_t m3World_OverlapHull(const m3World* world, m3Pos3 base, const m3Vec3* points, int32_t count, float radius, m3QueryFilter filter, m3ShapeId* idsOut, int32_t capacity);
Shapes within exact reach of a point cloud's hull, inflated by a radius; see above.
Parameters:
world: The world.base: The point the cloud is relative to.points: The cloud, base-relative.count: The number of points, 1 to 64.radius: The inflation radius, not negative.filter: The query filter; m3DefaultQueryFilter sees every shape.idsOut: Receives up to capacity shape ids, in ascending shape index order.capacity: idsOut's length, at least 0.Returns: The total number of shapes found; 0 on a refusal, which zeroes the array over its capacity and counts one misuse but a null world's: a null world, a negative capacity or a null array with a positive one, null points, a count outside 1 to 64, a base or point that is not finite, or a radius that is not finite or is negative.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
m3ExplosionDef m3DefaultExplosionDef(void);
Returns a def with pinned defaults (10 m radius, 5 m falloff, zero impulse, no carve, soft push 1, open filter) and a valid cookie.
Returns: The def, with the cookie m3World_Explode checks.
Thread safety. Safe from any thread.
void m3World_Explode(m3World* world, const m3ExplosionDef* def);
Apply the explosion now. Journaled; hostile defs apply nothing and journal nothing. Every push leaves its body within 1e5 m/s and rad/s. A null world does nothing. A null def, one m3DefaultExplosionDef did not make, a position that is not finite or past 1e15 m, a radius, falloff or voxel carve that is negative or not finite, an impulse per area that is NaN or past 1e10 either way, a soft push that is NaN or past 1e4 either way, or a call from host code the world is running, changes nothing, is not journaled and counts one misuse.
Parameters:
world: The world.def: The def, from m3DefaultExplosionDef.Thread safety. Safe from any thread; a world is used by one thread at a time.
uint64_t m3World_Hash(const m3World* world);
FNV-1a 64 over the deterministic state in canonical slot order: the step count, gravity and any tuning off its default, every id pool's identity (liveness, generations, free queue), and the bodies, shapes (the height field each one reads, voxel grids and mesh paint included), characters, soft bodies, vehicles, joints (limits, motors and collide flags included), water volumes and persistent contacts. Mesh geometry and height field samples are left out, since nothing changes them after create, and so are derived data and observers (trees, events, counters, the profile). The value every gate compares.
Parameters:
world: The world.Returns: The hash; 0 for a null world.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
int32_t m3World_GetBodies(const m3World* world, m3BodyId* idsOut, int32_t capacity);
Every live body or joint, up to capacity ids in ascending slot order; returns the total, which may exceed capacity, and a NULL array with capacity 0 measures. A refusal zeroes the array over its whole capacity; a success, an empty one included, writes only its entries; a list call only reads, so none is refused as busy.
Parameters:
world: The world.idsOut: Receives up to capacity body ids.capacity: idsOut's length, at least 0.Returns: The total number of live bodies; 0 on a refusal, which zeroes the array over its capacity and counts one misuse but a null world's: a null world, a negative capacity, or a null array with a positive one.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
int32_t m3World_GetJoints(const m3World* world, m3JointId* idsOut, int32_t capacity);
Every live joint, as m3World_GetBodies lists the bodies.
Parameters:
world: The world.idsOut: Receives up to capacity joint ids.capacity: idsOut's length, at least 0.Returns: The total number of live joints; 0 on a refusal, as m3World_GetBodies lists them.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
uint64_t m3World_GetStepCount(const m3World* world);
Returns the number of steps taken, which is snapshot state.
Parameters:
world: The world.Returns: The step count; 0 for a null world.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
m3Counters m3World_GetCounters(const m3World* world);
Returns the world's counters.
Parameters:
world: The world.Returns: The counters; zeros for a null world.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
m3MemoryUsage m3World_GetMemoryUsage(const m3World* world);
Returns the world's memory accounting.
Parameters:
world: The world.Returns: The usage; zeros for a null world.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
m3Profile m3World_GetProfile(const m3World* world);
Returns the last completed step's profile.
Parameters:
world: The world.Returns: The profile; zeros for a null world.
Thread safety. Safe from any thread; a world is used by one thread at a time, or by several readers at once.
M3_NODISCARD M3_API m3Result m3World_StartJournal(m3World* world, void* buffer, int64_t capacity);
Journal: every mutation of the world is a discrete recorded op, and replaying the stream through the same internal functions reproduces the world bit for bit. Start hands the world a caller-owned buffer (m3_errorState while a journal is already running); Stop sets bytesOut to the bytes written, or returns m3_errorCapacity when the buffer overflowed (m3_errorState when none was running), and any failure leaves bytesOut zero but a stop refused as busy, which leaves it as it was; Replay applies a stream to this world. A tape is laid out the same on every target (little-endian, each record as on x86-64) and never holds a def's padding, so the same calls write the same bytes anywhere. It starts with the 16-byte state prefix, written when the journal starts, so the buffer holds at least 16 bytes and a session of no op is those 16. Only the releases of the minor version that wrote a tape replay it. Sizes are 64-bit; on a 32-bit target Start refuses a capacity, and Replay a size, past SIZE_MAX with m3_errorInvalid.
Parameters:
world: The world.buffer: The caller's buffer the tape is written into.capacity: buffer's length in bytes, at least 16.Returns: m3_success; m3_errorInvalid for a null world or buffer, a capacity below 16 or one this target cannot address; m3_errorState while a journal runs; m3_errorBusy from host code the world is running. Each refusal but a null world's counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3World_StopJournal(m3World* world, int64_t* bytesOut);
Stops the journal and reports the tape's length, as described above.
Parameters:
world: The world.bytesOut: Receives the tape's length in bytes.Returns: m3_success; m3_errorCapacity when the buffer overflowed; m3_errorInvalid for a null world or bytesOut; m3_errorState when no journal runs; m3_errorBusy from host code the world is running. Each refusal but an overflow's and a null world's counts one misuse.
Thread safety. Safe from any thread; a world is used by one thread at a time.
M3_NODISCARD M3_API m3Result m3World_ReplayJournal(m3World* world, const void* data, int64_t size);
Replay a recorded session into this world. ATOMIC: on any refusal the world is restored to its pre-call state; a half-applied session is impossible. Returns m3_errorVersion for a tape another minor version wrote, m3_errorFormat for a damaged tape (truncation, corruption, an op that cannot re-mint its recorded id) and m3_errorCapacity when the world's allocator refuses what the replay or one of its ops needs. The back-out is taken before the first op so that it cannot fail: for the whole call the replay holds a snapshot of the world (m3World_GetSnapshotSize bytes) and a second copy of its mesh and height field content and mesh trees (about contentBytes of m3World_GetMemoryUsage) and arrays sized by the mesh, shape and voxel capacities. A tape that fits a tight allocator without that headroom is refused with m3_errorCapacity before any op runs.
Parameters:
world: The world.data: The tape.size: The tape's length in bytes.Returns: m3_success, a tape of the 16-byte prefix alone included; m3_errorInvalid for a null world, a negative size, one this target cannot address, or null data with a positive size; m3_errorVersion, m3_errorFormat or m3_errorCapacity as above, which count no misuse; m3_errorBusy from host code the world is running. The invalid and busy refusals count one misuse but a null world's. A replay is not recorded into a running journal, like a restore: stop a journal before replaying.
Thread safety. Safe from any thread; a world is used by one thread at a time.