physx_sys/
lib.rs

1//! # 🎳 physx-sys
2//!
3//! ![Build Status](https://github.com/EmbarkStudios/physx-rs/workflows/CI/badge.svg)
4//! [![Crates.io](https://img.shields.io/crates/v/physx-sys.svg)](https://crates.io/crates/physx-sys)
5//! [![Docs](https://docs.rs/physx-sys/badge.svg)](https://docs.rs/physx-sys)
6//! [![Contributor Covenant](https://img.shields.io/badge/contributor%20covenant-v1.4%20adopted-ff69b4.svg)](../CODE_OF_CONDUCT.md)
7//! [![Embark](https://img.shields.io/badge/embark-open%20source-blueviolet.svg)](http://embark.games)
8//!
9//! Unsafe automatically-generated Rust bindings for [NVIDIA PhysX 4.1](https://github.com/NVIDIAGameWorks/PhysX) C++ API.
10//!
11//! Please also see the [repository](https://github.com/EmbarkStudios/physx-rs) containing a work-in-progress safe wrapper.
12//!
13//! ## Presentation
14//!
15//! [Tomasz Stachowiak](https://github.com/h3r2tic) did a presentation at the Stockholm Rust Meetup on October 2019
16//! about this project that goes through the tecnical details of how C++ to Rust bindings of `physx-sys` works:
17//!
18//! [![](http://img.youtube.com/vi/RxtXGeDHu0w/0.jpg)](http://www.youtube.com/watch?v=RxtXGeDHu0w "An unholy fusion of
19//! Rust and C++ in physx-rs (Stockholm Rust Meetup, October 2019)")
20//!
21//!
22//! ## Basic usage
23//!
24//! ```Rust
25//! unsafe {
26//!     let foundation = physx_create_foundation();
27//!     let physics = physx_create_physics(foundation);
28//!
29//!     let mut scene_desc = PxSceneDesc_new(PxPhysics_getTolerancesScale(physics));
30//!     scene_desc.gravity = PxVec3 {
31//!         x: 0.0,
32//!         y: -9.81,
33//!         z: 0.0,
34//!     };
35//!
36//!     let dispatcher = PxDefaultCpuDispatcherCreate(2, null_mut());
37//!
38//!     scene_desc.cpuDispatcher = dispatcher as *mut PxCpuDispatcher;
39//!     scene_desc.filterShader = Some(PxDefaultSimulationFilterShader);
40//!
41//!     let scene = PxPhysics_createScene_mut(physics, &scene_desc);
42//!
43//!     // Your physics simulation goes here
44//! }
45//! ```
46//!
47//! ## Examples
48//!
49//! ### [Ball](examples/ball.rs)
50//!
51//! A simple example to showcase how to use physx-sys. It can be run with `cargo run --examples ball`.
52//!
53//! ```
54//!  o
55//!
56//!   o
57//!    o
58//!
59//!     o
60//!                       ooooooooo
61//!      o              oo         oo
62//!                    o             o
63//!       o           o               o
64//!                  o                 oo
65//!        o        o                    o
66//!                o                                ooooooo
67//!               o                       o       oo       oo
68//!         o    o                         o    oo           oo
69//!             o                           o  o               o    ooooooooo
70//!          o                                o                 o oo         oooooooooo oo
71//!
72//! ```
73//!
74//! ## How it works
75//!
76//! The binding is generated using a custom C++ app written against clang's
77//! [libtooling](https://clang.llvm.org/docs/LibTooling.html). It queries the compiler's abstract syntax tree, and maps
78//! the C++ PhysX functions and types to Rust using heuristics chosen specifically for this SDK. It is not a general
79//! C++ <-> Rust binding generator, and using it on other projects *will* likely crash and burn.
80//!
81//! Since C++ does not have a standardized and stable ABI, it's generally not safe to call it from Rust code; since
82//! PhysX exposes a C++ interface, we can't use it directly. That's why `physx-sys` generates both a Rust interface as
83//! well as a plain C wrapper. The C code is compiled into a static library at build time, and Rust then talks to C.
84//!
85//! In order to minimize the amount of work required to marshall data between the C wrapper and the original C++ API, we
86//! generate a **bespoke C wrapper for each build target**. The wrapper is based on metadata about structure layout
87//! extracted directly from compiling and running a tiny program against the PhysX SDK using the specific C++ compiler
88//! used in the build process.
89//!
90//! The build process comprises a few steps:
91//!
92//! 1. The `pxbind` utility uses `clang` to extract metadata about PhysX functions and types, and generates partial
93//! Rust and C bindings as `physx_generated.hpp` and `physx_generated.rs`. Those contain all function definitions, and
94//! a small subset of types. It also generates a C++ utility called `structgen` by emitting `structgen.cpp`.
95//! 2. `structgen` is compiled against the PhysX SDK, and generates all the remaining type wrappers. For each struct, it
96//! queries the size and offset of its members, and generates `structgen_out.hpp` and `structgen_out.rs`. The types are
97//! "plain old data" structs which will perfectly match the memory layout of the C++ types.
98//! 3. All the generated C types are compiled together to form `physx_api`, a static library for Rust to link with.
99//! 4. The Rust wrapper is compiled, and linked with PhysX and the C wrapper.
100//!
101//! Steps *2..4* are performed completely automatically from within `build.rs`, while step *1* is only necessary when
102//! upgrading the PhysX SDK or modifying the generator. As such, building and running `pxbind` is a manual task, and is
103//! currently only supported on \*nix systems.
104//!
105//! ## License
106//!
107//! Licensed under either of
108//!
109//! * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
110//! * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
111//!
112//! at your option.
113//!
114//! Note that the [PhysX C++ SDK](https://github.com/NVIDIAGameWorks/PhysX) has it's
115//! [own BSD 3 license](https://gameworksdocs.nvidia.com/PhysX/4.1/documentation/physxguide/Manual/License.html) and
116//! depends on [additional C++ third party libraries](https://github.com/NVIDIAGameWorks/PhysX/tree/4.1/externals).
117//!
118//! ### Contribution
119//!
120//! Unless you explicitly state otherwise, any contribution intentionally
121//! submitted for inclusion in the work by you, as defined in the Apache-2.0
122//! license, shall be dual licensed as above, without any additional terms or
123//! conditions.
124
125// crate-specific exceptions:
126#![allow(
127    unsafe_code,
128    non_upper_case_globals,
129    non_camel_case_types,
130    non_snake_case,
131    clippy::doc_markdown, // TODO: fixup comments and docs (though annoyingly complains about "PhysX")
132    clippy::unreadable_literal,
133    clippy::unused_unit,
134    clippy::upper_case_acronyms
135)]
136
137#[cfg(feature = "structgen")]
138include!(concat!(env!("OUT_DIR"), "/structgen_out.rs"));
139
140#[cfg(all(
141    not(feature = "structgen"),
142    target_os = "linux",
143    target_arch = "x86_64",
144))]
145include!("generated/unix/structgen.rs");
146
147#[cfg(all(
148    not(feature = "structgen"),
149    target_os = "linux",
150    target_arch = "aarch64",
151))]
152include!("generated/unix/structgen.rs");
153
154#[cfg(all(
155    not(feature = "structgen"),
156    target_os = "android",
157    target_arch = "x86_64",
158))]
159include!("generated/unix/structgen.rs");
160
161#[cfg(all(
162    not(feature = "structgen"),
163    target_os = "android",
164    target_arch = "aarch64",
165))]
166include!("generated/unix/structgen.rs");
167
168#[cfg(all(
169    not(feature = "structgen"),
170    target_os = "macos",
171    target_arch = "x86_64",
172))]
173include!("generated/unix/structgen.rs");
174
175#[cfg(all(
176    not(feature = "structgen"),
177    target_os = "macos",
178    target_arch = "aarch64",
179))]
180include!("generated/unix/structgen.rs");
181
182#[cfg(all(
183    not(feature = "structgen"),
184    target_os = "windows",
185    target_arch = "x86_64",
186    target_env = "msvc",
187))]
188include!("generated/x86_64-pc-windows-msvc/structgen.rs");
189
190include!("physx_generated.rs");
191
192use std::ffi::c_void;
193
194pub const fn version(major: u32, minor: u32, patch: u32) -> u32 {
195    (major << 24) + (minor << 16) + (patch << 8)
196}
197
198pub type CollisionCallback =
199    unsafe extern "C" fn(*mut c_void, *const PxContactPairHeader, *const PxContactPair, u32);
200
201pub type TriggerCallback = unsafe extern "C" fn(*mut c_void, *const PxTriggerPair, u32);
202
203pub type ConstraintBreakCallback = unsafe extern "C" fn(*mut c_void, *const PxConstraintInfo, u32);
204
205pub type WakeSleepCallback = unsafe extern "C" fn(*mut c_void, *const *const PxActor, u32, bool);
206
207pub type AdvanceCallback =
208    unsafe extern "C" fn(*mut c_void, *const *const PxRigidBody, *const PxTransform, u32);
209
210// Function pointers in Rust are normally not nullable (which is why they don't require unsafe to call)
211// but we need them to be, so we simply wrap them in Option<>. An Option<funcptr> is luckily represented
212// by the compiler as a simple pointer with null representing None, so this is compatible with the C struct.
213#[repr(C)]
214pub struct SimulationEventCallbackInfo {
215    // Callback for collision events.
216    pub collision_callback: Option<CollisionCallback>,
217    pub collision_user_data: *mut c_void,
218    // Callback for trigger shape events (an object entered or left a trigger shape).
219    pub trigger_callback: Option<TriggerCallback>,
220    pub trigger_user_data: *mut c_void,
221    // Callback for when a constraint breaks (such as a joint with a force limit)
222    pub constraint_break_callback: Option<ConstraintBreakCallback>,
223    pub constraint_break_user_data: *mut c_void,
224    // Callback for when an object falls asleep or is awoken.
225    pub wake_sleep_callback: Option<WakeSleepCallback>,
226    pub wake_sleep_user_data: *mut c_void,
227    // Callback to get the next pose early for objects (if flagged with eENABLE_POSE_INTEGRATION_PREVIEW).
228    pub advance_callback: Option<AdvanceCallback>,
229    pub advance_user_data: *mut c_void,
230}
231
232impl Default for SimulationEventCallbackInfo {
233    fn default() -> Self {
234        Self {
235            collision_callback: None,
236            collision_user_data: std::ptr::null_mut(),
237            trigger_callback: None,
238            trigger_user_data: std::ptr::null_mut(),
239            constraint_break_callback: None,
240            constraint_break_user_data: std::ptr::null_mut(),
241            wake_sleep_callback: None,
242            wake_sleep_user_data: std::ptr::null_mut(),
243            advance_callback: None,
244            advance_user_data: std::ptr::null_mut(),
245        }
246    }
247}
248
249pub type RaycastHitCallback = unsafe extern "C" fn(
250    *const PxRigidActor,
251    *const PxFilterData,
252    *const PxShape,
253    hit_flags: u32,
254    *const c_void,
255) -> PxQueryHitType;
256
257pub type PostFilterCallback =
258    unsafe extern "C" fn(*const PxFilterData, *const PxQueryHit, *const c_void) -> PxQueryHitType;
259
260#[repr(C)]
261pub struct FilterShaderCallbackInfo {
262    pub attributes0: u32,
263    pub attributes1: u32,
264    pub filterData0: PxFilterData,
265    pub filterData1: PxFilterData,
266    pub pairFlags: *mut PxPairFlags,
267    pub constantBlock: *const std::ffi::c_void,
268    pub constantBlockSize: u32,
269}
270
271pub type SimulationFilterShader =
272    unsafe extern "C" fn(*mut FilterShaderCallbackInfo) -> PxFilterFlags;
273
274pub type RaycastProcessTouchesCallback =
275    unsafe extern "C" fn(*const PxRaycastHit, u32, *mut c_void) -> bool;
276pub type SweepProcessTouchesCallback =
277    unsafe extern "C" fn(*const PxSweepHit, u32, *mut c_void) -> bool;
278pub type OverlapProcessTouchesCallback =
279    unsafe extern "C" fn(*const PxOverlapHit, u32, *mut c_void) -> bool;
280
281pub type FinalizeQueryCallback = unsafe extern "C" fn(*mut c_void);
282
283pub type AllocCallback =
284    unsafe extern "C" fn(u64, *const c_void, *const c_void, u32, *const c_void) -> *mut c_void;
285
286pub type DeallocCallback = unsafe extern "C" fn(*const c_void, *const c_void);
287
288pub type ZoneStartCallback =
289    unsafe extern "C" fn(*const i8, bool, u64, *const c_void) -> *mut c_void;
290
291pub type ZoneEndCallback = unsafe extern "C" fn(*const c_void, *const i8, bool, u64, *const c_void);
292
293pub type ErrorCallback =
294    unsafe extern "C" fn(PxErrorCode, *const i8, *const i8, u32, *const c_void);
295
296pub type AssertHandler = unsafe extern "C" fn(*const i8, *const i8, u32, *mut bool, *const c_void);
297
298extern "C" {
299    pub fn physx_create_foundation() -> *mut PxFoundation;
300    pub fn physx_create_foundation_with_alloc(
301        allocator: *mut PxDefaultAllocator,
302    ) -> *mut PxFoundation;
303    pub fn physx_create_physics(foundation: *mut PxFoundation) -> *mut PxPhysics;
304
305    pub fn get_default_allocator() -> *mut PxDefaultAllocator;
306    pub fn get_default_error_callback() -> *mut PxDefaultErrorCallback;
307
308    /// Destroy the returned callback object using PxQueryFilterCallback_delete.
309    pub fn create_raycast_filter_callback(
310        actor_to_ignore: *const PxRigidActor,
311    ) -> *mut PxQueryFilterCallback;
312
313    /// Destroy the returned callback object using PxQueryFilterCallback_delete.
314    pub fn create_raycast_filter_callback_func(
315        callback: RaycastHitCallback,
316        userdata: *mut c_void,
317    ) -> *mut PxQueryFilterCallback;
318
319    /// Destroy the returned callback object using PxQueryFilterCallback_delete.
320    pub fn create_pre_and_post_raycast_filter_callback_func(
321        preFilter: RaycastHitCallback,
322        postFilter: PostFilterCallback,
323        userdata: *mut c_void,
324    ) -> *mut PxQueryFilterCallback;
325
326    pub fn create_raycast_buffer() -> *mut PxRaycastCallback;
327    pub fn create_sweep_buffer() -> *mut PxSweepCallback;
328    pub fn create_overlap_buffer() -> *mut PxOverlapCallback;
329
330    pub fn create_raycast_callback(
331        process_touches_callback: RaycastProcessTouchesCallback,
332        finalize_query_callback: FinalizeQueryCallback,
333        touches_buffer: *mut PxRaycastHit,
334        num_touches: u32,
335        userdata: *mut c_void,
336    ) -> *mut PxRaycastCallback;
337    pub fn create_sweep_callback(
338        process_touches_callback: SweepProcessTouchesCallback,
339        finalize_query_callback: FinalizeQueryCallback,
340        touches_buffer: *mut PxSweepHit,
341        num_touches: u32,
342        userdata: *mut c_void,
343    ) -> *mut PxSweepCallback;
344    pub fn create_overlap_callback(
345        process_touches_callback: OverlapProcessTouchesCallback,
346        finalize_query_callback: FinalizeQueryCallback,
347        touches_buffer: *mut PxOverlapHit,
348        num_touches: u32,
349        userdata: *mut c_void,
350    ) -> *mut PxOverlapCallback;
351
352    pub fn delete_raycast_callback(callback: *mut PxRaycastCallback);
353    pub fn delete_sweep_callback(callback: *mut PxSweepCallback);
354    pub fn delete_overlap_callback(callback: *mut PxOverlapCallback);
355
356    pub fn create_alloc_callback(
357        alloc_callback: AllocCallback,
358        dealloc_callback: DeallocCallback,
359        userdata: *mut c_void,
360    ) -> *mut PxAllocatorCallback;
361
362    pub fn create_profiler_callback(
363        zone_start_callback: ZoneStartCallback,
364        zone_end_callback: ZoneEndCallback,
365        userdata: *mut c_void,
366    ) -> *mut PxProfilerCallback;
367
368    pub fn get_alloc_callback_user_data(alloc_callback: *mut PxAllocatorCallback) -> *mut c_void;
369
370    pub fn create_error_callback(
371        error_callback: ErrorCallback,
372        userdata: *mut c_void,
373    ) -> *mut PxErrorCallback;
374
375    pub fn create_assert_handler(
376        error_callback: AssertHandler,
377        userdata: *mut c_void,
378    ) -> *mut PxAssertHandler;
379
380    pub fn get_default_simulation_filter_shader() -> *mut c_void;
381
382    /// Create a C++ proxy callback which will forward contact events to `Callback`.
383    /// The returned pointer must be freed by calling `destroy_contact_callback` when done using.
384    #[deprecated]
385    pub fn create_contact_callback(
386        callback: CollisionCallback,
387        userdata: *mut c_void,
388    ) -> *mut PxSimulationEventCallback;
389    /// Deallocates the PxSimulationEventCallback that has previously been created
390    #[deprecated()]
391    pub fn destroy_contact_callback(callback: *mut PxSimulationEventCallback);
392
393    /// New interface to handle simulation events, replacing create_contact_callback.
394    pub fn create_simulation_event_callbacks(
395        callbacks: *const SimulationEventCallbackInfo,
396    ) -> *mut PxSimulationEventCallback;
397
398    pub fn get_simulation_event_info(
399        callback: *mut PxSimulationEventCallback,
400    ) -> *mut SimulationEventCallbackInfo;
401
402    pub fn destroy_simulation_event_callbacks(callback: *mut PxSimulationEventCallback);
403
404    /// Override the default filter shader in the scene with a custom function.
405    /// If call_default_filter_shader_first is set to true, this will first call the
406    /// built-in PhysX filter (that matches Physx 2.8 behavior) before your callback.
407    pub fn enable_custom_filter_shader(
408        scene_desc: *mut PxSceneDesc,
409        shader: SimulationFilterShader,
410        call_default_filter_shader_first: u32,
411    );
412
413    #[doc(hidden)]
414    /// Should only be used in testing etc! This isn't generated as we don't generate op functions.
415    pub fn PxAssertHandler_opCall_mut(
416        self_: *mut PxAssertHandler,
417        expr: *const i8,
418        file: *const i8,
419        line: i32,
420        ignore: *mut bool,
421    ) -> ();
422}