oxijolt_sys/lib.rs
1//! Unsafe bindings to [Jolt Physics] 5.6.0 through the [joltc] C wrapper.
2//!
3//! Everything here is `bindgen` output over joltc's `include/joltc.h` plus this
4//! fork's `native/joltc_ext/joltc_ext.h`, and keeps their `JPH_*` names. The output is
5//! committed under `src/bindings/`, one file per ABI family and configuration, so building
6//! needs no libclang; the `bindgen` feature generates it at build time instead. The
7//! supported targets are the registry in `build/targets.rs`; 32-bit targets are not
8//! supported. The
9//! extension adds functions in joltc's naming that are compiled into the joltc
10//! archive: a `JPH_StateRecorder`, `JPH_CharacterVirtual_SaveState` and
11//! `RestoreState`, `JPH_CharacterVirtual_ExtendedUpdate2` and
12//! `RefreshContacts2` with explicit gravity, filters and temp allocator,
13//! `JPH_VehicleConstraint_AsConstraint`, the `Constraint` base of a vehicle
14//! constraint, and for ragdolls `JPH_RagdollSettings_SetPart`, the typed
15//! `JPH_RagdollSettings_SetPartToParentSwingTwist`, `_SetPartToParentHinge` and
16//! `_SetPartToParentSixDOF`, `JPH_RagdollSettings_CalculateConstraintPriorities`,
17//! the swing-twist motor states (`JPH_SwingTwistConstraint_SetSwingMotorState`,
18//! `_GetSwingMotorState`, `_SetTwistMotorState`, `_GetTwistMotorState`), its
19//! `SetTargetOrientationBS` and `GetRotationInConstraintSpace`, and
20//! `JPH_HingeConstraint_SetTargetOrientationBS`, and materials with user data
21//! (`JPH_PhysicsMaterial_Create2`, `JPH_PhysicsMaterial_GetUserData`,
22//! `JPH_ConvexShapeSettings_SetMaterial`, `JPH_HeightFieldShapeSettings_Create2`), the
23//! sub-shape pair of a removed contact (`JPH_SubShapeIDPair_GetBody1ID` and its three siblings),
24//! a contact listener whose validate callback gets the collide result without faces
25//! (`JPH_ContactListener2_*`, `JPH_PhysicsSystem_SetContactListener2`) and a soft body contact
26//! listener (`JPH_SoftBodyContactListener_*`,
27//! `JPH_PhysicsSystem_SetSoftBodyContactListener`, `JPH_SoftBodyManifold_*`), and shapes saved
28//! to bytes with their children and materials and restored (`JPH_Shape_SaveBinaryState`,
29//! `JPH_Shape_RestoreBinaryState`, `JPH_ShapeBinaryState_*`). The safe API lives in the
30//! `oxijolt` crate.
31//!
32//! # Features
33//! - `asserts`: compile Jolt with its debug assertions. joltc's default handler prints a failed
34//! assertion and then executes a breakpoint (`__debugbreak` on MSVC), so raw users should
35//! install their own with `JPH_SetAssertFailureHandler` before `JPH_Init`. The handler is one
36//! process-global joltc slot, and the `oxijolt` crate installs its own.
37//! - `double-precision`: world positions ([`Real`], `JPH_RVec3`, `JPH_RMat4`) use `f64`.
38//! - `cross-platform-deterministic`: build Jolt with its cross-platform deterministic
39//! floating point settings (slower; same results across compilers and platforms).
40//! - `debug-renderer`: compile Jolt's debug renderer into the native libraries and bind joltc's
41//! debug drawing functions.
42//! - `bindgen`: generate the bindings at build time with libclang instead of using the
43//! committed ones. It does not add supported targets.
44//!
45//! # Native build and `JOLTC_LIB_DIR`
46//! By default the build script builds joltc and Jolt from the `vendor/` submodules with
47//! CMake, always in Release. Set `JOLTC_LIB_DIR` to an install prefix produced by an
48//! earlier build (`OUT_DIR/joltc`) to skip CMake: it holds `lib/` with the joltc and Jolt
49//! static libraries, `include/joltc.h`, `include/joltc_ext.h` and
50//! `oxijolt-sys-manifest.txt`. A prefix is specific
51//! to the target, the C runtime, the crate features and the pinned joltc and Jolt
52//! commits; the build script validates all of these against the manifest and refuses a
53//! mismatch.
54//!
55//! # Using the raw API
56//! joltc's own contract, as observed in its source:
57//! - Shape creators such as `JPH_BoxShape_Create` return a shape that holds **one**
58//! reference, and `JPH_Shape_Destroy` releases one. Bodies keep their own reference, so
59//! the creator releases its reference once it no longer needs the shape.
60//! - `JPH_PhysicsSystem_Destroy` deletes the broad-phase layer interface and both layer
61//! filters passed in `JPH_PhysicsSystemSettings`. Do not destroy them yourself.
62//! - `JPH_Init` is guarded by a plain `bool`, and creating or destroying a physics system
63//! writes an unsynchronised global map. Call `JPH_Init` once, and create and destroy
64//! systems from one thread at a time.
65//! - `JPH_PhysicsSystem_Update` uses one global temp allocator. Use
66//! `JPH_PhysicsSystem_Update2` with a per-world `JPH_TempAllocator` instead.
67//! - joltc's `JPH_CharacterVirtual_Update`, `ExtendedUpdate`, `RefreshContacts`,
68//! `WalkStairs`, `StickToFloor` and `SetShape` use joltc's one global temp
69//! allocator and are not thread-safe. Use `JPH_CharacterVirtual_ExtendedUpdate2`
70//! and `JPH_CharacterVirtual_RefreshContacts2` with a per-world allocator instead.
71//! - `JPH_CharacterVirtualSettings_Init` (and `JPH_CharacterSettings_Init`) create an
72//! empty shape and its settings on every call, each holding a reference nobody
73//! releases. Fill the settings field by field instead.
74//! - A recorder passed to `JPH_CharacterVirtual_RestoreState` must hold a complete
75//! stream written by `JPH_CharacterVirtual_SaveState`.
76//! - `JPH_JobSystemThreadPool_Create` maps `numThreads <= 0` to "as many as there are
77//! hardware threads", so pass a positive worker count when the count matters.
78//! - joltc's object-layer, body and shape filters (`JPH_ObjectLayerFilter_*`,
79//! `JPH_BodyFilter_*`, `JPH_ShapeFilter_*`) call one process-global proc table per filter
80//! type. The `oxijolt` crate installs those tables once and owns them. Code that links
81//! both crates must not call `JPH_*Filter_SetProcs` for these three types, and must not pass
82//! filters it created with `JPH_*Filter_Create` to queries, because the callbacks of
83//! `oxijolt` would receive their `userData`.
84//! - joltc's body activation and character contact listeners and the extension's contact
85//! listener (`JPH_ContactListener2_*`) and soft body contact listener also call one
86//! process-global proc table each. The `oxijolt` crate installs them once and owns them: code
87//! that links both crates must not call `JPH_ContactListener2_SetProcs`,
88//! `JPH_BodyActivationListener_SetProcs`, `JPH_CharacterContactListener_SetProcs` or
89//! `JPH_SoftBodyContactListener_SetProcs`, nor create listeners of these types, whose
90//! `userData` the callbacks of `oxijolt` would receive. joltc's own contact listener (`JPH_ContactListener_*`) is not used by `oxijolt`
91//! and is free for other code.
92//! - A vehicle constraint must be registered both as a constraint
93//! (`JPH_PhysicsSystem_AddConstraint` with `JPH_VehicleConstraint_AsConstraint`) and as a
94//! step listener (`JPH_PhysicsSystem_AddStepListener` with
95//! `JPH_VehicleConstraint_AsPhysicsStepListener`), and its collision tester must be set
96//! before the first step. Remove it from both before its last reference is released
97//! (`JPH_Constraint_Destroy` on the `AsConstraint` pointer) and before its body is
98//! destroyed.
99//! - `JPH_VehicleEngineSettings_Init` allocates a `JPH_LinearCurve` for `normalizedTorque`
100//! that the caller must destroy with `JPH_LinearCurve_Destroy`.
101//! - The `JPH_Wheel_GetContact*` getters are meaningful only while `JPH_Wheel_HasContact`
102//! returns true.
103//! - `JPH_RagdollSettings_CreateRagdoll` dereferences null when the world cannot hold every
104//! part. Check `JPH_PhysicsSystem_GetNumBodies() + parts <= JPH_PhysicsSystem_GetMaxBodies()`
105//! first, with no body created concurrently. The skeleton must list parents before their
106//! children.
107//! - A ragdoll destroys its bodies through its physics system when its last reference is
108//! released: remove it from the system (`JPH_Ragdoll_RemoveFromPhysicsSystem`) before that,
109//! and release it before the system is destroyed.
110//! - `JPH_Ragdoll_DriveToPoseUsingMotors` drives only swing-twist and hinge parts (any other
111//! constraint is a Jolt assertion) and needs
112//! `JPH_RagdollSettings_CalculateBodyIndexToConstraintIndex` to have run.
113//! - `JPH_RagdollSettings_SetPartToParent` handles swing-twist only and drops the constraint
114//! base settings, the spring modes and the motor torque limits; the typed
115//! `JPH_RagdollSettings_SetPartToParent*` functions of the extension keep every field.
116//! - A motor state other than `JPH_MotorState_Off` needs valid motor settings (Jolt
117//! `MotorSettings::IsValid`).
118//! - These joltc functions are not bound: `JPH_RagdollSettings_DisableParentChildCollisions`,
119//! `JPH_Ragdoll_SetPose2`, `JPH_Ragdoll_GetPose2`, `JPH_SkeletonMapper_Initialize`,
120//! `JPH_SkeletonMapper_LockAllTranslations`, `JPH_SkeletonMapper_LockTranslations`,
121//! `JPH_SkeletonMapper_Map` and `JPH_SkeletonMapper_MapReverse`. They reinterpret a
122//! 4-aligned `JPH_Mat4` array as Jolt's 16-aligned `Mat44`, which is undefined
123//! behaviour for most arrays a caller can pass.
124//! - The debug drawing functions (`JPH_DebugRenderer_*`, `JPH_BodyDrawFilter_*`,
125//! `JPH_PhysicsSystem_Draw*`, `JPH_Shape_Draw`) exist only with the `debug-renderer` feature,
126//! which also compiles Jolt's debug renderer into the native libraries.
127//! - Jolt's `DebugRenderer` is a process singleton and joltc's `JPH_DebugRenderer_SetProcs` sets
128//! one global proc table. With the `debug-renderer` feature of `oxijolt`, that crate
129//! installs the table and creates a renderer during `PhysicsWorld::debug_lines`; code that
130//! links both crates must not call `JPH_DebugRenderer_SetProcs` or keep its own
131//! `JPH_DebugRenderer` alive.
132//!
133//! [Jolt Physics]: https://github.com/jrouwe/JoltPhysics
134//! [joltc]: https://github.com/amerkoleci/joltc
135
136mod generated;
137mod layout;
138
139pub use generated::*;
140
141/// Scalar type of world positions: `f64` with the `double-precision` feature, `f32` otherwise.
142#[cfg(feature = "double-precision")]
143pub type Real = f64;
144
145/// Scalar type of world positions: `f64` with the `double-precision` feature, `f32` otherwise.
146#[cfg(not(feature = "double-precision"))]
147pub type Real = f32;
148
149/// Whether the native library was built with Jolt's assertions (the `asserts` feature).
150pub const ASSERTS_ENABLED: bool = cfg!(feature = "asserts");
151
152/// Whether the native library was built with Jolt's cross-platform determinism (the
153/// `cross-platform-deterministic` feature).
154pub const CROSS_PLATFORM_DETERMINISTIC_ENABLED: bool =
155 cfg!(feature = "cross-platform-deterministic");
156
157/// Jolt Physics commit the native library is built from (the `vendor/JoltPhysics` submodule).
158pub const JOLT_COMMIT: &str = env!("OXIJOLT_SYS_JOLT_COMMIT");
159
160/// joltc commit the native library is built from (the `vendor/joltc` submodule).
161pub const JOLTC_COMMIT: &str = env!("OXIJOLT_SYS_JOLTC_COMMIT");
162
163/// Revision of this fork's joltc additions (`native/joltc_ext/`) in the native library. A
164/// prebuilt prefix of another revision is refused by the build script.
165pub const JOLTC_EXT_REVISION: &str = env!("OXIJOLT_SYS_JOLTC_EXT_REVISION");
166
167/// `JPH_Mat4_RotationTranslation` under the name double precision uses.
168///
169/// joltc declares the `JPH_RMat4_*` functions only for double precision; in single precision
170/// `JPH_RMat4` is `JPH_Mat4` and `JPH_RVec3` is `JPH_Vec3`, so this forwards to the `JPH_Mat4_*`
171/// function and callers name one function in both builds.
172///
173/// # Safety
174/// As for the joltc function: `result` is valid for writing one matrix, `rotation` and
175/// `translation` are valid for reading.
176#[cfg(not(feature = "double-precision"))]
177#[allow(non_snake_case)]
178pub unsafe fn JPH_RMat4_RotationTranslation(
179 result: *mut JPH_RMat4,
180 rotation: *const JPH_Quat,
181 translation: *const JPH_RVec3,
182) {
183 // SAFETY: the caller upholds the joltc function's contract, and the types are identical in
184 // single precision.
185 unsafe { JPH_Mat4_RotationTranslation(result, rotation, translation) }
186}