1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
// Author: Tom Olsson <tom.olsson@embark-studios.com>
// Copyright © 2019, Embark Studios, all rights reserved.
// Created: 19 June 2019

#![warn(clippy::all)]

/*!
Wrapper implementation for PxRigidDynamic
*/

use crate::{
    geometry::Geometry,
    math::PxTransform,
    owner::Owner,
    physics::Physics,
    rigid_actor::RigidActor,
    rigid_body::RigidBody,
    shape::Shape,
    traits::{Class, PxFlags, UserData},
};

use enumflags2::{bitflags, BitFlags};

use std::{marker::PhantomData, ptr::drop_in_place};

use physx_sys::{
    phys_PxCreateDynamic, PxRigidActor_release_mut, PxRigidDynamicLockFlag,
    PxRigidDynamicLockFlags, PxRigidDynamic_getContactReportThreshold,
    PxRigidDynamic_getKinematicTarget, PxRigidDynamic_getRigidDynamicLockFlags,
    PxRigidDynamic_getSleepThreshold, PxRigidDynamic_getSolverIterationCounts,
    PxRigidDynamic_getStabilizationThreshold, PxRigidDynamic_getWakeCounter,
    PxRigidDynamic_isSleeping, PxRigidDynamic_putToSleep_mut,
    PxRigidDynamic_setContactReportThreshold_mut, PxRigidDynamic_setKinematicTarget_mut,
    PxRigidDynamic_setRigidDynamicLockFlag_mut, PxRigidDynamic_setRigidDynamicLockFlags_mut,
    PxRigidDynamic_setSleepThreshold_mut, PxRigidDynamic_setSolverIterationCounts_mut,
    PxRigidDynamic_setStabilizationThreshold_mut, PxRigidDynamic_setWakeCounter_mut,
    PxRigidDynamic_wakeUp_mut,
};

///////////////////////////////////////////////////
// Flags
pub type RigidDynamicLockFlags = BitFlags<RigidDynamicLockFlag>;

impl PxFlags for RigidDynamicLockFlags {
    type Target = PxRigidDynamicLockFlags;

    fn into_px(self) -> Self::Target {
        PxRigidDynamicLockFlags { mBits: self.bits() }
    }

    fn from_px(flags: Self::Target) -> Self {
        unsafe { BitFlags::from_bits_unchecked(flags.mBits) }
    }
}

#[bitflags]
#[derive(Copy, Clone, Debug)]
#[repr(u8)]
pub enum RigidDynamicLockFlag {
    LockLinearX = 1 << 0,
    LockLinearY = 1 << 1,
    LockLinearZ = 1 << 2,
    LockAngularX = 1 << 3,
    LockAngularY = 1 << 4,
    LockAngularZ = 1 << 5,
}

impl From<RigidDynamicLockFlag> for PxRigidDynamicLockFlag::Enum {
    fn from(value: RigidDynamicLockFlag) -> Self {
        match value {
            RigidDynamicLockFlag::LockLinearX => PxRigidDynamicLockFlag::eLOCK_LINEAR_X,
            RigidDynamicLockFlag::LockLinearY => PxRigidDynamicLockFlag::eLOCK_LINEAR_Y,
            RigidDynamicLockFlag::LockLinearZ => PxRigidDynamicLockFlag::eLOCK_LINEAR_Z,
            RigidDynamicLockFlag::LockAngularX => PxRigidDynamicLockFlag::eLOCK_ANGULAR_X,
            RigidDynamicLockFlag::LockAngularY => PxRigidDynamicLockFlag::eLOCK_ANGULAR_Y,
            RigidDynamicLockFlag::LockAngularZ => PxRigidDynamicLockFlag::eLOCK_ANGULAR_Z,
        }
    }
}

impl From<PxRigidDynamicLockFlag::Enum> for RigidDynamicLockFlag {
    fn from(flag: PxRigidDynamicLockFlag::Enum) -> Self {
        match flag {
            PxRigidDynamicLockFlag::eLOCK_LINEAR_X => RigidDynamicLockFlag::LockLinearX,
            PxRigidDynamicLockFlag::eLOCK_LINEAR_Y => RigidDynamicLockFlag::LockLinearY,
            PxRigidDynamicLockFlag::eLOCK_LINEAR_Z => RigidDynamicLockFlag::LockLinearZ,
            PxRigidDynamicLockFlag::eLOCK_ANGULAR_X => RigidDynamicLockFlag::LockAngularX,
            PxRigidDynamicLockFlag::eLOCK_ANGULAR_Y => RigidDynamicLockFlag::LockAngularY,
            PxRigidDynamicLockFlag::eLOCK_ANGULAR_Z => RigidDynamicLockFlag::LockAngularZ,
            _ => unreachable!("Invalid enum variant."),
        }
    }
}

///////////////////////////////////////////////////

/// A new type wrapper for PxRigidDynamic.  Parametrized by it's user data type,
/// and the type of it's Shapes.
#[repr(transparent)]
pub struct PxRigidDynamic<D, Geom: Shape> {
    pub(crate) obj: physx_sys::PxRigidDynamic,
    phantom_user_data: PhantomData<(D, Geom)>,
}

unsafe impl<U, Geom: Shape> UserData for PxRigidDynamic<U, Geom> {
    type UserData = U;

    fn user_data_ptr(&self) -> &*mut std::ffi::c_void {
        &self.obj.userData
    }

    fn user_data_ptr_mut(&mut self) -> &mut *mut std::ffi::c_void {
        &mut self.obj.userData
    }
}

impl<D, Geom: Shape> Drop for PxRigidDynamic<D, Geom> {
    fn drop(&mut self) {
        unsafe {
            drop_in_place(self.get_user_data_mut() as *mut _);
            PxRigidActor_release_mut(self.as_mut_ptr());
        }
    }
}

unsafe impl<P, D, Geom: Shape> Class<P> for PxRigidDynamic<D, Geom>
where
    physx_sys::PxRigidDynamic: Class<P>,
{
    fn as_ptr(&self) -> *const P {
        self.obj.as_ptr()
    }

    fn as_mut_ptr(&mut self) -> *mut P {
        self.obj.as_mut_ptr()
    }
}

unsafe impl<D: Send, Geom: Shape + Send> Send for PxRigidDynamic<D, Geom> {}
unsafe impl<D: Sync, Geom: Shape + Sync> Sync for PxRigidDynamic<D, Geom> {}

impl<D, Geom: Shape> RigidActor for PxRigidDynamic<D, Geom> {
    type Shape = Geom;
}

impl<D, Geom: Shape> RigidDynamic for PxRigidDynamic<D, Geom> {}

pub trait RigidDynamic: Class<physx_sys::PxRigidDynamic> + RigidBody + UserData {
    /// Create a new RigidDynamic.
    fn new(
        physics: &mut impl Physics,
        transform: PxTransform,
        geometry: &impl Geometry,
        material: &mut <Self::Shape as Shape>::Material,
        density: f32,
        shape_transform: PxTransform,
        user_data: Self::UserData,
    ) -> Option<Owner<Self>> {
        unsafe {
            RigidDynamic::from_raw(
                phys_PxCreateDynamic(
                    physics.as_mut_ptr(),
                    transform.as_ptr(),
                    geometry.as_ptr(),
                    material.as_mut_ptr(),
                    density,
                    shape_transform.as_ptr(),
                ),
                user_data,
            )
        }
    }

    /// Create a new Owner wrapper around a raw pointer.
    /// # Safety
    /// Owner's own the pointer they wrap, using the pointer after dropping the Owner,
    /// or creating multiple Owners from the same pointer will cause UB.  Use `into_ptr` to
    /// retrieve the pointer and consume the Owner without dropping the pointee.
    /// Initializes user data.
    unsafe fn from_raw(
        ptr: *mut physx_sys::PxRigidDynamic,
        user_data: Self::UserData,
    ) -> Option<Owner<Self>> {
        let actor = (ptr as *mut Self).as_mut();
        Owner::from_raw(actor?.init_user_data(user_data))
    }

    /// Get the user data.
    fn get_user_data(&self) -> &Self::UserData {
        // Safety: all construction goes through from_raw, which calls init_user_data
        unsafe { UserData::get_user_data(self) }
    }

    /// Get the user data.
    fn get_user_data_mut(&mut self) -> &mut Self::UserData {
        // Safety: all construction goes through from_raw, which calls init_user_data
        unsafe { UserData::get_user_data_mut(self) }
    }

    /// Get the contact report threshold.  If the force between two actors exceeds this threshold for either actor,
    /// a contact report will be generated in accordance with the filter shader.
    fn get_contact_report_threshold(&self) -> f32 {
        unsafe { PxRigidDynamic_getContactReportThreshold(self.as_ptr()) }
    }

    /// Returns a copy of the target transform if the actor is knematically controlled and has a target set,
    /// otherwise it returns None.
    fn get_kinematic_target(&self) -> Option<PxTransform> {
        let mut transform = PxTransform::default();
        unsafe {
            if PxRigidDynamic_getKinematicTarget(self.as_ptr(), transform.as_mut_ptr()) {
                Some(transform)
            } else {
                None
            }
        }
    }

    /// Get the lock flags.
    fn get_rigid_dynamic_lock_flags(&self) -> RigidDynamicLockFlags {
        unsafe {
            RigidDynamicLockFlags::from_px(PxRigidDynamic_getRigidDynamicLockFlags(self.as_ptr()))
        }
    }

    /// Get the sleep threshold.  If the actor's mass-normalized kinetic energy is below this value,
    /// the actor might go to sleep.
    fn get_sleep_threshold(&self) -> f32 {
        unsafe { PxRigidDynamic_getSleepThreshold(self.as_ptr()) }
    }

    /// Get the number of (position, velocity) iterations done by the solver.
    fn get_solver_iteration_counts(&self) -> (u32, u32) {
        let mut pos_iters = 0;
        let mut vel_iters = 0;
        unsafe {
            PxRigidDynamic_getSolverIterationCounts(self.as_ptr(), &mut vel_iters, &mut pos_iters);
        }
        (pos_iters, vel_iters)
    }

    /// Get the stabilization threshold.  Actors with mass-normalized kinetic energy may participate in stabilization.
    fn get_stabilization_threshold(&self) -> f32 {
        unsafe { PxRigidDynamic_getStabilizationThreshold(self.as_ptr()) }
    }

    /// Get the wake counter.
    fn get_wake_counter(&self) -> f32 {
        unsafe { PxRigidDynamic_getWakeCounter(self.as_ptr()) }
    }

    /// Returns true if the actor is sleeping.  Sleeping actors are not simulated.  If an actor is sleeping,
    /// it's linear and angular velocities are zero, no force or torque updates are pending, and the wake counter is zero.
    fn is_sleeping(&self) -> bool {
        unsafe { PxRigidDynamic_isSleeping(self.as_ptr()) }
    }

    /// Put the actor to sleep.  Pending force and torque is cleared, and the wake counter and linear and angular
    /// velocities are all set to zero.
    fn put_to_sleep(&mut self) {
        unsafe { PxRigidDynamic_putToSleep_mut(self.as_mut_ptr()) }
    }

    /// Set the contact report threshold, used when determining if a contact report should be generated.
    fn set_contact_report_threshold(&mut self, threshold: f32) {
        unsafe { PxRigidDynamic_setContactReportThreshold_mut(self.as_mut_ptr(), threshold) }
    }

    /// Set the kinematic target of the actor.  Set an actor as kinematic using `RigidBodyFlag::Kinematic`.
    /// The actor will have it's velocity set such that it gets moved to the desired pose in a single timestep,
    /// then the velocity will be zeroed.  Movement along a path requires continuous calls.  Consecutive calls
    /// in a single frame will overwrite the prior.
    fn set_kinematic_target(&mut self, target: &PxTransform) {
        unsafe { PxRigidDynamic_setKinematicTarget_mut(self.as_mut_ptr(), target.as_ptr()) }
    }

    /// Set a lock flag, preventing movement along or about an axis.
    fn set_rigid_dynamic_lock_flag(&mut self, flag: RigidDynamicLockFlag, value: bool) {
        unsafe { PxRigidDynamic_setRigidDynamicLockFlag_mut(self.as_mut_ptr(), flag.into(), value) }
    }

    /// Set the lock flags.
    fn set_rigid_dynamic_lock_flags(&mut self, flags: RigidDynamicLockFlags) {
        unsafe { PxRigidDynamic_setRigidDynamicLockFlags_mut(self.as_mut_ptr(), flags.into_px()) }
    }

    /// Set the mass normalized kinetic energy under which an actor is a candidate for being slept.  Default is
    /// 5e-5f * PxTolerancesScale.speed ^ 2.  Value is clamped to range [0.0 .. ].
    fn set_sleep_threshold(&mut self, mut threshold: f32) {
        if threshold.is_sign_negative() {
            threshold = 0.0
        };
        unsafe { PxRigidDynamic_setSleepThreshold_mut(self.as_mut_ptr(), threshold) }
    }

    /// Set the number of solver iterations for the position and velocity solvers clamped to range [1..=255].
    /// Defualt is position = 4 and velocity = 1. If bodies are oscillating, increase the position iterations.
    /// If bodies are being depenetrated too quickly, increase the velocity iterations.
    fn set_solver_iteration_counts(
        &mut self,
        min_position_iterations: u32,
        min_velocity_iterations: u32,
    ) {
        unsafe {
            PxRigidDynamic_setSolverIterationCounts_mut(
                self.as_mut_ptr(),
                min_position_iterations,
                min_velocity_iterations,
            )
        }
    }

    /// Set the stabilization threshold.  Actors with mass-normalized kinetic energy above this value will
    /// not participate in stabilization.
    fn set_stabilization_threshold(&mut self, threshold: f32) {
        unsafe { PxRigidDynamic_setStabilizationThreshold_mut(self.as_mut_ptr(), threshold) }
    }

    /// Sets the wake counter.  This is the minimum amount of time until an actor must spend below the
    /// sleep threshold before it is put to sleep.  Setting this to a positive value will wake the actor.
    /// Default is 0.4, value is in seconds.
    fn set_wake_counter(&mut self, wake_counter: f32) {
        unsafe { PxRigidDynamic_setWakeCounter_mut(self.as_mut_ptr(), wake_counter) }
    }

    /// Wake the actor.  May wake touching actors.  Sets the wake counter to the `wake_counter_reset_value`
    /// set at scene creation.
    fn wake_up(&mut self) {
        unsafe { PxRigidDynamic_wakeUp_mut(self.as_mut_ptr()) }
    }
}