Skip to content

Commit

Permalink
Atomics and Materials (#873)
Browse files Browse the repository at this point in the history
- shape material
- friction and restitution callbacks from narrow phase
- platform atomic wrappers
- removed experimental:c11atomics flag

#812 #872
  • Loading branch information
erincatto authored Jan 22, 2025
1 parent c7ce16a commit f248ccc
Show file tree
Hide file tree
Showing 33 changed files with 461 additions and 209 deletions.
5 changes: 3 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ endif()

# Deterministic math
# https://box2d.org/posts/2024/08/determinism/
# todo make this apply to ClangCL
if (MINGW OR APPLE OR UNIX)
add_compile_options(-ffp-contract=off)
endif()
Expand Down Expand Up @@ -100,7 +101,6 @@ if(PROJECT_IS_TOP_LEVEL)

# enkiTS is used by all the test apps, but not directly by the Box2D library
if(BOX2D_UNIT_TESTS OR BOX2D_SAMPLES OR BOX2D_BENCHMARKS)
SET(ENKITS_BUILD_EXAMPLES OFF CACHE BOOL "Build enkiTS examples")

# Emscripten pthread support for enkiTS
if(EMSCRIPTEN)
Expand All @@ -111,7 +111,8 @@ if(PROJECT_IS_TOP_LEVEL)
string(APPEND CMAKE_EXE_LINKER_FLAGS " ${EMSCRIPTEN_PTHREADS_LINKER_FLAGS}")
endif()

# Used in tests and samples
# Task system used in tests and samples
set(ENKITS_BUILD_EXAMPLES OFF CACHE BOOL "Build enkiTS examples")
FetchContent_Declare(
enkits
GIT_REPOSITORY https://github.com/dougbinks/enkiTS.git
Expand Down
4 changes: 0 additions & 4 deletions benchmark/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@ add_executable(benchmark ${BOX2D_BENCHMARK_FILES})

set_target_properties(benchmark PROPERTIES C_STANDARD 17)

if (MSVC AND CMAKE_C_COMPILER_ID MATCHES "MSVC")
target_compile_options(benchmark PRIVATE /experimental:c11atomics)
endif()

target_link_libraries(benchmark PRIVATE box2d shared enkiTS)

source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} PREFIX "" FILES ${BOX2D_BENCHMARK_FILES})
18 changes: 9 additions & 9 deletions benchmark/amd7950x_avx2/joint_grid.csv
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
threads,fps
1,197.415
2,338.192
3,485.363
4,590.58
5,678.894
6,755.337
7,830.03
8,889.992
threads,ms
1,2565.3
2,1533.85
3,1053.01
4,865.702
5,748.989
6,658.623
7,613.633
8,578.973
18 changes: 9 additions & 9 deletions benchmark/amd7950x_avx2/large_pyramid.csv
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
threads,fps
1,337.398
2,599.766
3,853.652
4,1095.24
5,1288.22
6,1467.1
7,1669.81
8,1704.72
threads,ms
1,1584.03
2,841.862
3,598.747
4,471.697
5,396.306
6,347.983
7,309.086
8,308.832
18 changes: 9 additions & 9 deletions benchmark/amd7950x_avx2/many_pyramids.csv
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
threads,fps
1,82.5412
2,156.573
3,233.64
4,294.31
5,357.121
6,420.298
7,487.163
8,537.355
threads,ms
1,2663.34
2,1407.85
3,934.506
4,725.271
5,590.288
6,502.513
7,422.693
8,395.369
18 changes: 9 additions & 9 deletions benchmark/amd7950x_avx2/rain.csv
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
threads,fps
1,158.379
2,253.381
3,337.197
4,408.427
5,475.14
6,530.178
7,583.798
8,633.102
threads,ms
1,6526.9
2,4017.74
3,3052.28
4,2493.5
5,2149.12
6,1911.45
7,1735.97
8,1625.71
18 changes: 9 additions & 9 deletions benchmark/amd7950x_avx2/smash.csv
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
threads,fps
1,194.531
2,299.76
3,389.501
4,469.022
5,532.045
6,580.977
7,620.559
8,655.217
threads,ms
1,1562.06
2,1020.55
3,781.193
4,661.318
5,580.115
6,530.502
7,489.672
8,467.998
18 changes: 9 additions & 9 deletions benchmark/amd7950x_avx2/spinner.csv
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
threads,fps
1,342.697
2,549.335
3,711.477
4,889.473
5,1011.82
6,1141.73
7,1261.39
8,1338.51
threads,ms
1,4106.89
2,2635.21
3,1986.32
4,1614.21
5,1420.63
6,1272.06
7,1157.16
8,1091.25
18 changes: 9 additions & 9 deletions benchmark/amd7950x_avx2/tumbler.csv
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
threads,fps
1,461.248
2,726.229
3,947.347
4,1152.31
5,1335.66
6,1483.59
7,1613.59
8,1715.86
threads,ms
1,1613.69
2,1061.88
3,810.738
4,670.874
5,578.959
6,519.473
7,479.842
8,437.851
2 changes: 1 addition & 1 deletion benchmark/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ int main( int argc, char** argv )
continue;
}

fprintf( file, "threads, ms\n" );
fprintf( file, "threads,ms\n" );
for ( int threadIndex = 1; threadIndex <= maxThreadCount; ++threadIndex )
{
fprintf( file, "%d,%g\n", threadIndex, minTime[threadIndex - 1] );
Expand Down
13 changes: 13 additions & 0 deletions include/box2d/box2d.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,12 @@ B2_API void b2World_SetUserData( b2WorldId worldId, void* userData );
/// Get the user data pointer.
B2_API void* b2World_GetUserData( b2WorldId worldId );

/// Set the friction callback. Passing NULL resets to default.
B2_API void b2World_SetFrictionCallback( b2WorldId worldId, b2FrictionCallback* callback );

/// Set the restitution callback. Passing NULL resets to default.
B2_API void b2World_SetRestitutionCallback( b2WorldId worldId, b2RestitutionCallback* callback );

/// Dump memory stats to box2d_memory.txt
B2_API void b2World_DumpMemoryStats( b2WorldId worldId );

Expand Down Expand Up @@ -552,6 +558,13 @@ B2_API void b2Shape_SetRestitution( b2ShapeId shapeId, float restitution );
/// Get the shape restitution
B2_API float b2Shape_GetRestitution( b2ShapeId shapeId );

/// Set the shape material identifier
/// @see b2ShapeDef::material
B2_API void b2Shape_SetMaterial( b2ShapeId shapeId, int material );

/// Get the shape material identifier
B2_API int b2Shape_GetMaterial( b2ShapeId shapeId );

/// Get the shape filter
B2_API b2Filter b2Shape_GetFilter( b2ShapeId shapeId );

Expand Down
36 changes: 21 additions & 15 deletions include/box2d/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,16 @@ typedef void* b2EnqueueTaskCallback( b2TaskCallback* task, int itemCount, int mi
/// @ingroup world
typedef void b2FinishTaskCallback( void* userTask, void* userContext );

/// Optional friction mixing callback. This intentionally provides no context objects because this is called
/// from a worker thread.
/// @warning This function should not attempt to modify Box2D state or user application state.
typedef float b2FrictionCallback( float frictionA, int materialA, float frictionB, int materialB );

/// Optional restitution mixing callback. This intentionally provides no context objects because this is called
/// from a worker thread.
/// @warning This function should not attempt to modify Box2D state or user application state.
typedef float b2RestitutionCallback( float restitutionA, int materialA, float restitutionB, int materialB );

/// Result from b2World_RayCastClosest
/// @ingroup world
typedef struct b2RayResult
Expand All @@ -62,16 +72,6 @@ typedef struct b2RayResult
bool hit;
} b2RayResult;

/// Mixing rules for friction and restitution
typedef enum b2MixingRule
{
b2_mixAverage,
b2_mixGeometricMean,
b2_mixMultiply,
b2_mixMinimum,
b2_mixMaximum
} b2MixingRule;

/// World definition used to create a simulation world.
/// Must be initialized using b2DefaultWorldDef().
/// @ingroup world
Expand Down Expand Up @@ -108,11 +108,11 @@ typedef struct b2WorldDef
/// Maximum linear speed. Usually meters per second.
float maximumLinearSpeed;

/// Mixing rule for friction. Default is b2_mixGeometricMean.
b2MixingRule frictionMixingRule;
/// Optional mixing callback for friction. The default uses sqrt(frictionA * frictionB).
b2FrictionCallback* frictionCallback;

/// Mixing rule for restitution. Default is b2_mixMaximum.
b2MixingRule restitutionMixingRule;
/// Optional mixing callback for restitution. The default uses max(restitutionA, restitutionB).
b2RestitutionCallback* restitutionCallback;

/// Can bodies go to sleep to improve performance
bool enableSleep;
Expand Down Expand Up @@ -341,12 +341,18 @@ typedef struct b2ShapeDef
/// The Coulomb (dry) friction coefficient, usually in the range [0,1].
float friction;

/// The restitution (bounce) usually in the range [0,1].
/// The coefficient of restitution (bounce) usually in the range [0,1].
/// https://en.wikipedia.org/wiki/Coefficient_of_restitution
float restitution;

/// The rolling resistance usually in the range [0,1].
/// todo
float rollingResistance;

/// User material identifier. This is passed with query results and to friction and restitution
/// combining functions. It is not used internally.
int material;

/// The density, usually in kg/m^2.
float density;

Expand Down
3 changes: 1 addition & 2 deletions samples/sample.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,6 @@ Sample::Sample( Settings& settings )
worldDef.userTaskContext = this;
worldDef.enableSleep = settings.enableSleep;

worldDef.restitutionMixingRule = b2_mixMaximum;

m_worldId = b2CreateWorld( &worldDef );
m_textLine = 30;
m_textIncrement = 22;
Expand Down Expand Up @@ -345,6 +343,7 @@ void Sample::Step( Settings& settings )
char buffer[256] = { 0 };
static_assert( std::size( s.colorCounts ) == 12 );

// todo fix this
int offset = snprintf( buffer, 256, "colors: " );
for ( int i = 0; i < 12; ++i )
{
Expand Down
18 changes: 16 additions & 2 deletions samples/sample_bodies.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,16 @@ class Character : public Sample

static int sampleCharacter = RegisterSample( "Bodies", "Character", Character::Create );

float FrictionCallback( float, int, float, int )
{
return 0.1f;
}

float RestitutionCallback( float, int, float, int )
{
return 1.0f;
}

class Weeble : public Sample
{
public:
Expand All @@ -480,6 +490,10 @@ class Weeble : public Sample
g_camera.m_zoom = 25.0f * 0.5f;
}

// Test friction and restitution callbacks
b2World_SetFrictionCallback( m_worldId, FrictionCallback );
b2World_SetRestitutionCallback( m_worldId, RestitutionCallback );

b2BodyId groundId = b2_nullBodyId;
{
b2BodyDef bodyDef = b2DefaultBodyDef();
Expand Down Expand Up @@ -892,7 +906,7 @@ class Pivot : public Sample
m_lever = 3.0f;
b2Vec2 r = { 0.0f, -m_lever };

float omega = b2Cross(v, r) / b2Dot(r, r);
float omega = b2Cross( v, r ) / b2Dot( r, r );
b2Body_SetAngularVelocity( m_bodyId, omega );

b2Polygon box = b2MakeBox( 0.1f, m_lever );
Expand All @@ -911,7 +925,7 @@ class Pivot : public Sample
b2Vec2 r = b2Body_GetWorldVector( m_bodyId, { 0.0f, -m_lever } );

b2Vec2 vp = v + b2CrossSV( omega, r );
g_draw.DrawString( 5, m_textLine, "pivot velocity = (%g, %g)", vp.x, vp.y);
g_draw.DrawString( 5, m_textLine, "pivot velocity = (%g, %g)", vp.x, vp.y );
m_textLine += m_textIncrement;
}

Expand Down
2 changes: 2 additions & 0 deletions samples/sample_events.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

#include <GLFW/glfw3.h>
#include <imgui.h>
#include <stdio.h>
#include <vector>

class SensorFunnel : public Sample
Expand Down Expand Up @@ -1600,6 +1601,7 @@ class SensorTypes : public Sample
continue;
}

// todo fix this
start += snprintf( buffer + start, sizeof( buffer ) - start, "%s, ", name );
}

Expand Down
6 changes: 0 additions & 6 deletions samples/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,8 @@ struct Settings
void Load();

int sampleIndex = 0;
// int windowWidth = 3840;
// int windowHeight = 2160;
int windowWidth = 1920;
int windowHeight = 1080;
// int windowWidth = 1280;
// int windowHeight = 720;
// int windowWidth = 800;
// int windowHeight = 600;
float hertz = 60.0f;
int subStepCount = 4;
int workerCount = 1;
Expand Down
6 changes: 1 addition & 5 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ set(BOX2D_SOURCE_FILES
arena_allocator.h
array.c
array.h
atomic.h
bitset.c
bitset.h
body.c
Expand Down Expand Up @@ -137,11 +138,6 @@ if (MSVC)
# Enable asserts in release with debug info
target_compile_definitions(box2d PUBLIC "$<$<CONFIG:RELWITHDEBINFO>:B2_ENABLE_ASSERT>")

# Atomics are still considered experimental in Visual Studio 17.8
if (CMAKE_C_COMPILER_ID MATCHES "MSVC")
target_compile_options(box2d PRIVATE /experimental:c11atomics)
endif()

# All warnings
target_compile_options(box2d PRIVATE /W4)

Expand Down
Loading

0 comments on commit f248ccc

Please sign in to comment.