diff --git a/vendor/box3d/box3d.odin b/vendor/box3d/box3d.odin index 834592c82..f4b3208af 100644 --- a/vendor/box3d/box3d.odin +++ b/vendor/box3d/box3d.odin @@ -59,7 +59,7 @@ foreign lib { SetAllocator :: proc(allocFcn: AllocFcn, freeFcn: FreeFcn) --- // Total bytes allocated by Box3D - GetByteCount :: proc() -> i32 --- + GetByteCount :: proc() -> c.int --- // Override the default assert callback. // @param assertFcn a non-null assert callback @@ -113,9 +113,9 @@ foreign lib { // Simple djb2 hash function for determinism testing Hash :: proc(hash: u32, data: [^]u8, count: c.int) -> u32 --- - // Dump file support functions - WriteBinaryFile :: proc(data: rawptr, size: c.int, fileName: cstring) --- - ReadBinaryFile :: proc(prefix: cstring, fileName: cstring, memSize: ^c.int) -> rawptr --- + // // Dump file support functions + // WriteBinaryFile :: proc(data: rawptr, size: c.int, fileName: cstring) --- + // ReadBinaryFile :: proc(prefix: cstring, fileName: cstring, memSize: ^c.int) -> rawptr --- } @@ -479,7 +479,7 @@ foreign lib { // Replaying at a different count re-partitions the constraint graph, so the StateHash check // becomes a cross-thread determinism test. Adjustable later with RecPlayer_SetWorkerCount. // @return a new player, or NULL on bad header or deserialization failure - RecPlayer_Create :: proc(data: rawptr, size: c.int, workerCount: c.int) -> RecPlayer --- + RecPlayer_Create :: proc(data: rawptr, size: c.int, workerCount: c.int) -> RecPlayer --- // Destroy the player and free all memory. Restores the previous global length scale. RecPlayer_Destroy :: proc(player: ^RecPlayer) --- @@ -488,6 +488,12 @@ foreign lib { // @return true when a frame was stepped, false at end-of-recording RecPlayer_StepFrame :: proc(player: ^RecPlayer) -> bool --- + // Sub-step one frame. This will sub-step and return immediately after body creation. + // The next call will execute the time step. This allows bodies to be rendered + // at the creation pose. + RecPlayer_SubStepFrame :: procplayer: ^b3RecPlayer) --- + + // Rewind to frame 0 (in-place restore so the world id stays stable). RecPlayer_Restart :: proc(player: ^RecPlayer) --- @@ -507,6 +513,9 @@ foreign lib { // @return true when the op stream is exhausted RecPlayer_IsAtEnd :: proc(#by_ptr player: RecPlayer) -> bool --- + // @return true when the op stream is paused between body creation and world step. + RecPlayer_IsAtPreStep :: proc(#by_ptr player: b3RecPlayer) -> bool --- + // @return true when any StateHash mismatch has been detected RecPlayer_HasDiverged :: proc(#by_ptr player: RecPlayer) -> bool --- @@ -614,7 +623,7 @@ foreign lib { // properties regardless of the automatic mass setting. Body_SetType :: proc(bodyId: BodyId, type: BodyType) --- - // Set the body name. Up to B3_BODY_NAME_LENGTH characters including null termination. + // Set the body name. Body_SetName :: proc(bodyId: BodyId, name: cstring) --- // Get the body name. @@ -742,10 +751,10 @@ foreign lib { Body_GetWorldInverseRotationalInertia :: proc(bodyId: BodyId) -> Matrix3 --- // Get the center of mass position of the body in local space - Body_GetLocalCenterOfMass :: proc(bodyId: BodyId) -> Vec3 --- + Body_GetLocalCenter :: proc(bodyId: BodyId) -> Vec3 --- // Get the center of mass position of the body in world space - Body_GetWorldCenterOfMass :: proc(bodyId: BodyId) -> Pos --- + Body_GetWorldCenter :: proc(bodyId: BodyId) -> Pos --- // Override the body's mass properties. Normally this is computed automatically using the // shape geometry and density. This information is lost if a shape is added or removed or if the @@ -835,7 +844,7 @@ foreign lib { // Enable/disable hit events on all shapes // @see ShapeDef::enableHitEvents - Body_EnableHitEvents :: proc(bodyId: BodyId, enableHitEvents: bool) --- + Body_EnableHitEvents :: proc(bodyId: BodyId, flag: bool) --- // Get the world that owns this body Body_GetWorld :: proc(bodyId: BodyId) -> WorldId --- @@ -946,12 +955,18 @@ foreign lib { // Returns true if the shape is a sensor Shape_IsSensor :: proc(shapeId: ShapeId) -> bool --- + // Set the shape name. + Shape_SetName :: proc(shapeId: ShapeId, name: cstring) --- + + // Get the shape name. Returns an empty string if the name isn't set. + Shape_GetName :: proc(shapeId: ShapeId) -> cstring --- + // Set the user data for a shape Shape_SetUserData :: proc(shapeId: ShapeId, userData: rawptr) --- // Get the user data for a shape. This is useful when you get a shape id // from an event or query. - Shape_GetUserData :: proc(shapeId: ShapeId) --- + Shape_GetUserData :: proc(shapeId: ShapeId) --- // Set the mass density of a shape, usually in kg/m^3. // This will optionally update the mass properties on the parent body. diff --git a/vendor/box3d/box3d_collision.odin b/vendor/box3d/box3d_collision.odin index 26435fe6f..e80584f7a 100644 --- a/vendor/box3d/box3d_collision.odin +++ b/vendor/box3d/box3d_collision.odin @@ -71,7 +71,7 @@ foreign lib { DynamicTree_RayCast :: proc(#by_ptr tree: DynamicTree, #by_ptr input: RayCastInput, maskBits: u64, requireAllBits: bool, callback: TreeRayCastCallbackFcn, ctx: rawptr) -> TreeStats --- // Sweep an AABB through the tree. The box is in the tree's world float frame and the callback - // re-differences each shape at full precision against the query origin. Used by the large world + // re-differences each shape at full precision aganist the query origin. Used by the large world // spatial queries so the tree traversal stays float while the narrow phase stays precise. DynamicTree_BoxCast :: proc(#by_ptr tree: DynamicTree, #by_ptr input: BoxCastInput, maskBits: u64, requireAllBits: bool, callback: TreeBoxCastCallbackFcn, ctx: rawptr) -> TreeStats --- @@ -444,7 +444,8 @@ foreign lib { CollideCapsuleAndTriangle :: proc(manifold: ^LocalManifold, capacity: c.int, #by_ptr capsuleA: Capsule, #by_ptr triangleB: [3]Vec3, cache: ^SimplexCache) --- // Collide a hull and a triangle. - CollideHullAndTriangle :: proc(manifold: ^LocalManifold, capacity: c.int, #by_ptr hullA: HullData, v1, v2, v3: Vec3, triangleFlags: c.int, cache: ^SATCache) --- + CollideHullAndTriangle :: proc(manifold: ^LocalManifold, capacity: c.int, #by_ptr hullA: HullData, v1, v2, v3: Vec3, + triangleFlags: c.int, cache: ^SATCache, enableSpeculative: bool) --- // Collide a sphere and a triangle. CollideSphereAndTriangle :: proc(manifold: ^LocalManifold, capacity: c.int, #by_ptr sphereA: Sphere, #by_ptr triangleB: [3]Vec3) --- diff --git a/vendor/box3d/box3d_constants.odin b/vendor/box3d/box3d_constants.odin index 3cc8233ab..ccb93678a 100644 --- a/vendor/box3d/box3d_constants.odin +++ b/vendor/box3d/box3d_constants.odin @@ -118,15 +118,6 @@ AABB_MARGIN_FRACTION :: 0.125 // The time that a body must be still before it will go to sleep. In seconds. TIME_TO_SLEEP :: 0.5 -// Maximum length of the body name. Can be 0 if you don't need names. -// Note: this gates recording capability. -BODY_NAME_LENGTH :: 18 - -// Maximum length of the shape name. Can be 0 if you don't need names. -// Note: this gates recording capability. -// todo waiting on this because it breaks existing recordings -SHAPE_NAME_LENGTH :: 18 - // The maximum number of contact points between two touching shapes. MAX_MANIFOLD_POINTS :: 4 diff --git a/vendor/box3d/box3d_math.odin b/vendor/box3d/box3d_math.odin index ee7ac4528..43c43d5e0 100644 --- a/vendor/box3d/box3d_math.odin +++ b/vendor/box3d/box3d_math.odin @@ -89,10 +89,6 @@ SegmentDistanceResult :: struct { @(link_prefix="b3", default_calling_convention="c", require_results) foreign lib { - // @return is this float valid (finite and not NaN). - IsValidFloat :: proc(a: f32) -> bool --- - - // Compute an approximate arctangent in the range [-pi, pi] // This is hand coded for cross-platform determinism. The atan2f // function in the standard library is not cross-platform deterministic. diff --git a/vendor/box3d/box3d_types.odin b/vendor/box3d/box3d_types.odin index 4c6c784d6..42b72615f 100644 --- a/vendor/box3d/box3d_types.odin +++ b/vendor/box3d/box3d_types.odin @@ -370,7 +370,7 @@ BodyDef :: struct{ // Sleep speed threshold, default is 0.05 meters per second sleepThreshold: f32, - // Optional body name for debugging. Up to B3_BODY_NAME_LENGTH characters (including null termination) + // Optional body name for debugging. name: cstring, // Use this to store application specific body data. @@ -488,7 +488,7 @@ ShapeType :: enum c.int { // A capsule is an extruded sphere capsuleShape, - // A compound shape composed of up to 64K spheres, capsules, hulls, and meshes + // A baked compound shape composed of spheres, capsules, hulls, and meshes compoundShape, // A height field useful for terrain @@ -507,6 +507,9 @@ ShapeType :: enum c.int { // Used to create a shape // @ingroup shape ShapeDef :: struct { + // Optional shape name for debugging + name: cstring, + // Use this to store application specific shape data. userData: rawptr, @@ -557,8 +560,14 @@ ShapeDef :: struct { invokeContactCreation: bool, // Should the body update the mass properties when this shape is created. Default is true. + // Warning: if this is false, you MUST call b3Body_ApplyMassFromShapes or b3Body_SetMassData before simulating the world. updateBodyMass: bool, + // Enable speculative collision. Leave this true unless you care about reducing ghost collision + // more than continuous collision under rotation. + // Experimental: this can only disable speculative contact between hulls and triangles (meshes and height fields). + enableSpeculativeContact: bool, + // Used internally to detect a valid definition. DO NOT SET. internalValue: c.int, } @@ -2330,11 +2339,13 @@ COMPOUND_VERSION :: 0x830778DB07086EB4 ~ DYNAMIC_TREE_VERSION ~ MESH_VERSION ~ // a mesh with many materials, you can use it outside of the compound. MAX_COMPOUND_MESH_MATERIALS :: 4 -// The runtime data for a compound shape. This is a potentially large yet highly optimized +// The runtime data for a baked compound shape. This is a potentially large yet highly optimized // data structure. It can contain thousands of child shapes, yet at runtime it populates // into the world as a single shape in the runtime broad-phase. // This data structure has data living off the end and must be accessed using offsets. // Accessors are provided for user relevant data. +// Note: you don't need to use this to create runtime compounds. For runtime compounds you can +// add multiple shapes to a body using the regular shape creation functions. CompoundData :: struct { // The compound version is always first. version: u64, @@ -2891,6 +2902,9 @@ DebugDraw :: struct { // Option to draw the mass and center of mass of dynamic bodies drawMass: bool, + // Option to draw the sleep information for dynamic and kinematic bodies + drawSleep: bool, + // Option to draw body names drawBodyNames: bool, diff --git a/vendor/box3d/lib/box3d.lib b/vendor/box3d/lib/box3d.lib index 4bc6c5b21..0448b70ec 100644 Binary files a/vendor/box3d/lib/box3d.lib and b/vendor/box3d/lib/box3d.lib differ diff --git a/vendor/box3d/src/include/box3d/base.h b/vendor/box3d/src/include/box3d/base.h index 2c0bb93f3..25828b3fa 100644 --- a/vendor/box3d/src/include/box3d/base.h +++ b/vendor/box3d/src/include/box3d/base.h @@ -102,7 +102,7 @@ typedef void b3LogFcn( const char* message ); B3_API void b3SetAllocator( b3AllocFcn* allocFcn, b3FreeFcn* freeFcn ); /// Total bytes allocated by Box3D -B3_API int32_t b3GetByteCount( void ); +B3_API int b3GetByteCount( void ); /// Override the default assert callback. /// @param assertFcn a non-null assert callback @@ -186,8 +186,4 @@ B3_API void b3Sleep( int milliseconds ); #define B3_HASH_INIT 5381 B3_API uint32_t b3Hash( uint32_t hash, const uint8_t* data, int count ); -// Dump file support functions -B3_API void b3WriteBinaryFile( void* data, int size, const char* fileName ); -B3_API void* b3ReadBinaryFile( const char* prefix, const char* fileName, int* memSize ); - //! @endcond diff --git a/vendor/box3d/src/include/box3d/box3d.h b/vendor/box3d/src/include/box3d/box3d.h index 22756636a..05b69dd63 100644 --- a/vendor/box3d/src/include/box3d/box3d.h +++ b/vendor/box3d/src/include/box3d/box3d.h @@ -245,13 +245,6 @@ B3_API void b3World_RebuildStaticTree( b3WorldId worldId ); /// This is for internal testing B3_API void b3World_EnableSpeculative( b3WorldId worldId, bool flag ); -/// Dump world to a text file. Saves only awake bodies and associated static bodies. -/// Meshes are saved to binary b3m files. -B3_API void b3World_DumpAwake( b3WorldId worldId ); - -/// Dump world to a text file. Meshes are saved to binary b3m files. -B3_API void b3World_Dump( b3WorldId worldId ); - /** * @defgroup recording Recording * @brief Record and replay world state for debugging. @@ -315,12 +308,12 @@ typedef struct b3RecPlayer b3RecPlayer; /// Summary of a recording, read once at open so a viewer can frame and label it. typedef struct b3RecPlayerInfo { - int frameCount; // total recorded steps - int workerCount; // worker count requested for the replay world - float timeStep; // dt of the recorded steps - int subStepCount; // recorded sub-steps - float lengthScale; // length units per meter in effect when recorded - b3AABB bounds; // accumulated world bounds over the recording, zero-extent if unavailable + int frameCount; // total recorded steps + int workerCount; // worker count requested for the replay world + float timeStep; // dt of the recorded steps + int subStepCount; // recorded sub-steps + float lengthScale; // length units per meter in effect when recorded + b3AABB bounds; // accumulated world bounds over the recording, zero-extent if unavailable } b3RecPlayerInfo; /// Create a player over a recording. Owns a private copy of the bytes. @@ -335,10 +328,15 @@ B3_API b3RecPlayer* b3RecPlayer_Create( const void* data, int size, int workerCo /// Destroy the player and free all memory. Restores the previous global length scale. B3_API void b3RecPlayer_Destroy( b3RecPlayer* player ); -/// Advance one frame: dispatch ops until the next Step completes. +/// Advance one frame. dispatch ops until the next Step completes. /// @return true when a frame was stepped, false at end-of-recording B3_API bool b3RecPlayer_StepFrame( b3RecPlayer* player ); +/// Sub-step one frame. This will sub-step and return immediately after body creation. +/// The next call will execute the time step. This allows bodies to be rendered +/// at the creation pose. +B3_API void b3RecPlayer_SubStepFrame( b3RecPlayer* player ); + /// Rewind to frame 0 (in-place restore so the world id stays stable). B3_API void b3RecPlayer_Restart( b3RecPlayer* player ); @@ -358,6 +356,9 @@ B3_API int b3RecPlayer_GetFrameCount( const b3RecPlayer* player ); /// @return true when the op stream is exhausted B3_API bool b3RecPlayer_IsAtEnd( const b3RecPlayer* player ); +/// @return true when the op stream is paused between body creation and world step. +B3_API bool b3RecPlayer_IsAtPreStep( const b3RecPlayer* player ); + /// @return true when any StateHash mismatch has been detected B3_API bool b3RecPlayer_HasDiverged( const b3RecPlayer* player ); @@ -412,7 +413,7 @@ B3_API b3BodyId b3RecPlayer_GetBodyId( const b3RecPlayer* player, int index ); /// @param destroyDebugShape called when a replayed shape is removed; may be NULL /// @param context user context passed to both callbacks B3_API void b3RecPlayer_SetDebugShapeCallbacks( b3RecPlayer* player, b3CreateDebugShapeCallback* createDebugShape, - b3DestroyDebugShapeCallback* destroyDebugShape, void* context ); + b3DestroyDebugShapeCallback* destroyDebugShape, void* context ); /// Draw the spatial queries recorded during the most recently replayed frame, layered on top of the /// world. Call after b3World_Draw. NULL draw function pointers are skipped. @@ -438,23 +439,23 @@ typedef enum b3RecQueryType typedef struct b3RecQueryInfo { b3RecQueryType type; - b3QueryFilter filter; - b3AABB aabb; // world-space bounds of the query, swept for casts - b3Pos origin; // query origin (zero for overlap AABB) - b3Vec3 translation; // ray and cast translation - int hitCount; // number of recorded results - uint64_t key; // identity key, the hash of (id, name), 0 if untagged - uint64_t id; // query id, 0 if none - const char* name; // query label, NULL if none + b3QueryFilter filter; + b3AABB aabb; // world-space bounds of the query, swept for casts + b3Pos origin; // query origin (zero for overlap AABB) + b3Vec3 translation; // ray and cast translation + int hitCount; // number of recorded results + uint64_t key; // identity key, the hash of (id, name), 0 if untagged + uint64_t id; // query id, 0 if none + const char* name; // query label, NULL if none } b3RecQueryInfo; /// One result of a recorded spatial query. typedef struct b3RecQueryHit { b3ShapeId shape; - b3Pos point; - b3Vec3 normal; - float fraction; + b3Pos point; + b3Vec3 normal; + float fraction; } b3RecQueryHit; /// @return the number of spatial queries recorded for the most recently replayed frame @@ -500,10 +501,10 @@ B3_API b3BodyType b3Body_GetType( b3BodyId bodyId ); /// properties regardless of the automatic mass setting. B3_API void b3Body_SetType( b3BodyId bodyId, b3BodyType type ); -/// Set the body name. Up to B3_BODY_NAME_LENGTH characters including null termination. +/// Set the body name. B3_API void b3Body_SetName( b3BodyId bodyId, const char* name ); -/// Get the body name. +/// Get the body name. Returns an empty string if the name isn't set. B3_API const char* b3Body_GetName( b3BodyId bodyId ); /// Set the user data for a body @@ -628,10 +629,10 @@ B3_API float b3Body_GetInverseMass( b3BodyId bodyId ); B3_API b3Matrix3 b3Body_GetWorldInverseRotationalInertia( b3BodyId bodyId ); /// Get the center of mass position of the body in local space -B3_API b3Vec3 b3Body_GetLocalCenterOfMass( b3BodyId bodyId ); +B3_API b3Vec3 b3Body_GetLocalCenter( b3BodyId bodyId ); /// Get the center of mass position of the body in world space -B3_API b3Pos b3Body_GetWorldCenterOfMass( b3BodyId bodyId ); +B3_API b3Pos b3Body_GetWorldCenter( b3BodyId bodyId ); /// Override the body's mass properties. Normally this is computed automatically using the /// shape geometry and density. This information is lost if a shape is added or removed or if the @@ -721,7 +722,7 @@ B3_API bool b3Body_IsContactRecyclingEnabled( b3BodyId bodyId ); /// Enable/disable hit events on all shapes /// @see b3ShapeDef::enableHitEvents -B3_API void b3Body_EnableHitEvents( b3BodyId bodyId, bool enableHitEvents ); +B3_API void b3Body_EnableHitEvents( b3BodyId bodyId, bool flag ); /// Get the world that owns this body B3_API b3WorldId b3Body_GetWorld( b3BodyId bodyId ); @@ -767,8 +768,8 @@ B3_API bool b3Body_OverlapShape( b3BodyId bodyId, b3Pos origin, const b3ShapePro b3WorldTransform bodyTransform ); /// Collide a character mover with a specific body using a specified body transform. -B3_API int b3Body_CollideMover( b3BodyId bodyId, b3BodyPlaneResult* bodyPlanes, int planeCapacity, b3Pos origin, const b3Capsule* mover, - b3QueryFilter filter, b3WorldTransform bodyTransform ); +B3_API int b3Body_CollideMover( b3BodyId bodyId, b3BodyPlaneResult* bodyPlanes, int planeCapacity, b3Pos origin, + const b3Capsule* mover, b3QueryFilter filter, b3WorldTransform bodyTransform ); /** @} */ // body @@ -838,6 +839,12 @@ B3_API b3WorldId b3Shape_GetWorld( b3ShapeId shapeId ); /// Returns true if the shape is a sensor B3_API bool b3Shape_IsSensor( b3ShapeId shapeId ); +/// Set the shape name. +B3_API void b3Shape_SetName( b3ShapeId shapeId, const char* name ); + +/// Get the shape name. Returns an empty string if the name isn't set. +B3_API const char* b3Shape_GetName( b3ShapeId shapeId ); + /// Set the user data for a shape B3_API void b3Shape_SetUserData( b3ShapeId shapeId, void* userData ); diff --git a/vendor/box3d/src/include/box3d/collision.h b/vendor/box3d/src/include/box3d/collision.h index 30cc9579f..1ba0070a6 100644 --- a/vendor/box3d/src/include/box3d/collision.h +++ b/vendor/box3d/src/include/box3d/collision.h @@ -81,9 +81,6 @@ B3_API b3TreeStats b3DynamicTree_RayCast( const b3DynamicTree* tree, const b3Ray B3_API b3TreeStats b3DynamicTree_BoxCast( const b3DynamicTree* tree, const b3BoxCastInput* input, uint64_t maskBits, bool requireAllBits, b3TreeBoxCastCallbackFcn* callback, void* context ); -/// Validate this tree. For testing. -B3_API void b3DynamicTree_Validate( const b3DynamicTree* tree ); - /// Get the height of the binary tree. B3_API int b3DynamicTree_GetHeight( const b3DynamicTree* tree ); @@ -619,7 +616,7 @@ B3_API void b3CollideCapsuleAndTriangle( b3LocalManifold* manifold, int capacity /// Collide a hull and a triangle. B3_API void b3CollideHullAndTriangle( b3LocalManifold* manifold, int capacity, const b3HullData* hullA, b3Vec3 v1, b3Vec3 v2, - b3Vec3 v3, int triangleFlags, b3SATCache* cache ); + b3Vec3 v3, int triangleFlags, b3SATCache* cache, bool enableSpeculative ); /// Collide a sphere and a triangle. B3_API void b3CollideSphereAndTriangle( b3LocalManifold* manifold, int capacity, const b3Sphere* sphereA, diff --git a/vendor/box3d/src/include/box3d/constants.h b/vendor/box3d/src/include/box3d/constants.h index e32b73706..87dd56d7e 100644 --- a/vendor/box3d/src/include/box3d/constants.h +++ b/vendor/box3d/src/include/box3d/constants.h @@ -97,19 +97,6 @@ B3_API float b3GetStallThreshold( void ); /// The time that a body must be still before it will go to sleep. In seconds. #define B3_TIME_TO_SLEEP 0.5f -/// Maximum length of the body name. Can be 0 if you don't need names. -/// Note: this gates recording capability. -#ifndef B3_BODY_NAME_LENGTH -#define B3_BODY_NAME_LENGTH 18 -#endif - -/// Maximum length of the shape name. Can be 0 if you don't need names. -/// Note: this gates recording capability. -/// todo waiting on this because it breaks existing recordings -#ifndef B3_SHAPE_NAME_LENGTH -#define B3_SHAPE_NAME_LENGTH 18 -#endif - /// The maximum number of contact points between two touching shapes. #define B3_MAX_MANIFOLD_POINTS 4 diff --git a/vendor/box3d/src/include/box3d/math_functions.h b/vendor/box3d/src/include/box3d/math_functions.h index 7ef7354f2..b1f65acec 100644 --- a/vendor/box3d/src/include/box3d/math_functions.h +++ b/vendor/box3d/src/include/box3d/math_functions.h @@ -155,9 +155,6 @@ B3_INLINE int b3ClampInt( int a, int lower, int upper ) return a < lower ? lower : ( upper < a ? upper : a ); } -/// @return is this float valid (finite and not NaN). -B3_API bool b3IsValidFloat( float a ); - /// @return the absolute value of a float. B3_INLINE float b3AbsFloat( float a ) { diff --git a/vendor/box3d/src/include/box3d/types.h b/vendor/box3d/src/include/box3d/types.h index 2c75977f0..40e685357 100644 --- a/vendor/box3d/src/include/box3d/types.h +++ b/vendor/box3d/src/include/box3d/types.h @@ -302,7 +302,7 @@ typedef struct b3BodyDef /// Sleep speed threshold, default is 0.05 meters per second float sleepThreshold; - /// Optional body name for debugging. Up to B3_BODY_NAME_LENGTH characters (including null termination) + /// Optional body name for debugging. const char* name; /// Use this to store application specific body data. @@ -432,7 +432,7 @@ typedef enum b3ShapeType /// A capsule is an extruded sphere b3_capsuleShape, - /// A compound shape composed of up to 64K spheres, capsules, hulls, and meshes + /// A baked compound shape composed of spheres, capsules, hulls, and meshes b3_compoundShape, /// A height field useful for terrain @@ -455,6 +455,9 @@ typedef enum b3ShapeType /// @ingroup shape typedef struct b3ShapeDef { + /// Optional shape name for debugging + const char* name; + /// Use this to store application specific shape data. void* userData; @@ -505,8 +508,14 @@ typedef struct b3ShapeDef bool invokeContactCreation; /// Should the body update the mass properties when this shape is created. Default is true. + /// Warning: if this is false, you MUST call b3Body_ApplyMassFromShapes or b3Body_SetMassData before simulating the world. bool updateBodyMass; + /// Enable speculative collision. Leave this true unless you care about reducing ghost collision + /// more than continuous collision under rotation. + /// Experimental: this can only disable speculative contact between hulls and triangles (meshes and height fields). + bool enableSpeculativeContact; + /// Used internally to detect a valid definition. DO NOT SET. int internalValue; @@ -2405,11 +2414,13 @@ typedef struct b3CompoundDef /// a mesh with many materials, you can use it outside of the compound. #define B3_MAX_COMPOUND_MESH_MATERIALS 4 -/// The runtime data for a compound shape. This is a potentially large yet highly optimized +/// The runtime data for a baked compound shape. This is a potentially large yet highly optimized /// data structure. It can contain thousands of child shapes, yet at runtime it populates /// into the world as a single shape in the runtime broad-phase. /// This data structure has data living off the end and must be accessed using offsets. /// Accessors are provided for user relevant data. +/// Note: you don't need to use this to create runtime compounds. For runtime compounds you can +/// add multiple shapes to a body using the regular shape creation functions. typedef struct b3CompoundData { /// The compound version is always first. @@ -2997,6 +3008,9 @@ typedef struct b3DebugDraw /// Option to draw the mass and center of mass of dynamic bodies bool drawMass; + /// Option to draw the sleep information for dynamic and kinematic bodies + bool drawSleep; + /// Option to draw body names bool drawBodyNames;