Skip to content

Commit 0f192cd

Browse files
authored
Bounding box performance experiments (#829)
- adjusted AABB margin based on performance testing - compute rotation between vectors - added macOS samples to GitHub actions #833, #835
1 parent 87e13e4 commit 0f192cd

18 files changed

+104
-220
lines changed

.github/workflows/build.yml

+14-2
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ jobs:
8686
run: ./bin/${{env.BUILD_TYPE}}/test
8787

8888
samples-windows:
89-
name: windows
89+
name: samples-windows
9090
runs-on: windows-latest
9191
steps:
9292

@@ -102,4 +102,16 @@ jobs:
102102

103103
- name: Build
104104
run: cmake --build ${{github.workspace}}/build --config Release
105-
105+
106+
samples-macos:
107+
name: samples-macos
108+
runs-on: macos-latest
109+
110+
steps:
111+
- uses: actions/checkout@v4
112+
113+
- name: Configure CMake
114+
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=Release -DBOX2D_SAMPLES=ON -DBUILD_SHARED_LIBS=OFF -DBOX2D_UNIT_TESTS=OFF
115+
116+
- name: Build
117+
run: cmake --build ${{github.workspace}}/build --config Release

docs/FAQ.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ Box2D also does not have exact collision. There is no continuous collision betwe
9494
Making a worms clone requires arbitrarily destructible terrain. This is beyond the scope of Box2D, so you will have to figure out how to do this on your own.
9595

9696
### Tile Based Environment
97-
Using many boxes for your terrain may not work well because box-like characters can get snagged on internal corners. Box2D proves chain shapes for smooth collision, see `b2ChainDef`. In general you should avoid using a rectangular character because collision tolerances will still lead to undesirable snagging. Box2D provides capsules and rounded polygons that may work better for characters.
97+
Using many boxes for your terrain may not work well because box-like characters can get snagged on internal corners. Box2D provides chain shapes for smooth collision, see `b2ChainDef`. In general you should avoid using a rectangular character because collision tolerances will still lead to undesirable snagging. Box2D provides capsules and rounded polygons that may work better for characters.
9898

9999
### Asteroid Type Coordinate Systems
100100
Box2D does not have any support for coordinate frame wrapping. You would likely need to customize Box2D for this purpose. You may need to use a different broad-phase for this to work.

include/box2d/collision.h

+8-6
Original file line numberDiff line numberDiff line change
@@ -249,17 +249,17 @@ B2_API bool b2PointInCapsule( b2Vec2 point, const b2Capsule* shape );
249249
/// Test a point for overlap with a convex polygon in local space
250250
B2_API bool b2PointInPolygon( b2Vec2 point, const b2Polygon* shape );
251251

252-
/// Ray cast versus circle in shape local space. Initial overlap is treated as a miss.
252+
/// Ray cast versus circle shape in local space. Initial overlap is treated as a miss.
253253
B2_API b2CastOutput b2RayCastCircle( const b2RayCastInput* input, const b2Circle* shape );
254254

255-
/// Ray cast versus capsule in shape local space. Initial overlap is treated as a miss.
255+
/// Ray cast versus capsule shape in local space. Initial overlap is treated as a miss.
256256
B2_API b2CastOutput b2RayCastCapsule( const b2RayCastInput* input, const b2Capsule* shape );
257257

258-
/// Ray cast versus segment in shape local space. Optionally treat the segment as one-sided with hits from
258+
/// Ray cast versus segment shape in local space. Optionally treat the segment as one-sided with hits from
259259
/// the left side being treated as a miss.
260260
B2_API b2CastOutput b2RayCastSegment( const b2RayCastInput* input, const b2Segment* shape, bool oneSided );
261261

262-
/// Ray cast versus polygon in shape local space. Initial overlap is treated as a miss.
262+
/// Ray cast versus polygon shape in local space. Initial overlap is treated as a miss.
263263
B2_API b2CastOutput b2RayCastPolygon( const b2RayCastInput* input, const b2Polygon* shape );
264264

265265
/// Shape cast versus a circle. Initial overlap is treated as a miss.
@@ -348,8 +348,10 @@ typedef struct b2DistanceProxy
348348
float radius;
349349
} b2DistanceProxy;
350350

351-
/// Used to warm start b2Distance. Set count to zero on first call or
352-
/// use zero initialization.
351+
/// Used to warm start the GJK simplex. If you call this function multiple times with nearby
352+
/// transforms this might improve performance. Otherwise you can zero initialize this.
353+
/// The distance cache must be initialized to zero on the first call.
354+
/// Users should generally just zero initialize this structure for each call.
353355
typedef struct b2DistanceCache
354356
{
355357
/// The number of stored simplex points

include/box2d/math_functions.h

+8
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,9 @@ B2_INLINE b2Rot b2MakeRot( float angle )
342342
return B2_LITERAL( b2Rot ){ cs.cosine, cs.sine };
343343
}
344344

345+
/// Compute the rotation between two unit vectors
346+
B2_API b2Rot b2ComputeRotationBetweenUnitVectors( b2Vec2 v1, b2Vec2 v2 );
347+
345348
/// Is this rotation normalized?
346349
B2_INLINE bool b2IsNormalized( b2Rot q )
347350
{
@@ -352,6 +355,7 @@ B2_INLINE bool b2IsNormalized( b2Rot q )
352355

353356
/// Normalized linear interpolation
354357
/// https://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/
358+
/// https://web.archive.org/web/20170825184056/http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/
355359
B2_INLINE b2Rot b2NLerp( b2Rot q1, b2Rot q2, float t )
356360
{
357361
float omt = 1.0f - t;
@@ -499,6 +503,9 @@ B2_INLINE b2Vec2 b2InvTransformPoint( b2Transform t, const b2Vec2 p )
499503
return B2_LITERAL( b2Vec2 ){ t.q.c * vx + t.q.s * vy, -t.q.s * vx + t.q.c * vy };
500504
}
501505

506+
/// Multiply two transforms. If the result is applied to a point p local to frame B,
507+
/// the transform would first convert p to a point local to frame A, then into a point
508+
/// in the world frame.
502509
/// v2 = A.q.Rot(B.q.Rot(v1) + B.p) + A.p
503510
/// = (A.q * B.q).Rot(v1) + A.q.Rot(B.p) + A.p
504511
B2_INLINE b2Transform b2MulTransforms( b2Transform A, b2Transform B )
@@ -509,6 +516,7 @@ B2_INLINE b2Transform b2MulTransforms( b2Transform A, b2Transform B )
509516
return C;
510517
}
511518

519+
/// Creates a transform that converts a local point in frame B to a local point in frame A.
512520
/// v2 = A.q' * (B.q * v1 + B.p - A.p)
513521
/// = A.q' * B.q * v1 + A.q' * (B.p - A.p)
514522
B2_INLINE b2Transform b2InvMulTransforms( b2Transform A, b2Transform B )

include/box2d/types.h

+6
Original file line numberDiff line numberDiff line change
@@ -969,6 +969,9 @@ typedef struct b2SensorBeginTouchEvent
969969
} b2SensorBeginTouchEvent;
970970

971971
/// An end touch event is generated when a shape stops overlapping a sensor shape.
972+
/// You will not get an end event if you do anything that destroys contacts outside
973+
/// of the world step. These include things like setting the transform, destroying a body
974+
/// or shape, or changing a filter or body type.
972975
typedef struct b2SensorEndTouchEvent
973976
{
974977
/// The id of the sensor shape
@@ -1010,6 +1013,9 @@ typedef struct b2ContactBeginTouchEvent
10101013
} b2ContactBeginTouchEvent;
10111014

10121015
/// An end touch event is generated when two shapes stop touching.
1016+
/// You will not get an end event if you do anything that destroys contacts outside
1017+
/// of the world step. These include things like setting the transform, destroying a body
1018+
/// or shape, or changing a filter or body type.
10131019
typedef struct b2ContactEndTouchEvent
10141020
{
10151021
/// Id of the first shape

samples/draw.cpp

+2-7
Original file line numberDiff line numberDiff line change
@@ -633,11 +633,6 @@ struct GLTriangles
633633
GLint m_projectionUniform;
634634
};
635635

636-
struct Transform
637-
{
638-
float x, y, c, s;
639-
};
640-
641636
struct CircleData
642637
{
643638
b2Vec2 position;
@@ -781,7 +776,7 @@ struct GLCircles
781776

782777
struct SolidCircleData
783778
{
784-
Transform transform;
779+
b2Transform transform;
785780
float radius;
786781
RGBA8 rgba;
787782
};
@@ -926,7 +921,7 @@ struct GLSolidCircles
926921

927922
struct CapsuleData
928923
{
929-
Transform transform;
924+
b2Transform transform;
930925
float radius;
931926
float length;
932927
RGBA8 rgba;

samples/main.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ static inline int CompareSamples( const void* a, const void* b )
111111
return result;
112112
}
113113

114-
static void SortTests()
114+
static void SortSamples()
115115
{
116116
qsort( g_sampleEntries, g_sampleCount, sizeof( SampleEntry ), CompareSamples );
117117
}
@@ -462,7 +462,7 @@ static void UpdateUI()
462462

463463
ImGuiTreeNodeFlags nodeFlags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick;
464464

465-
if ( ImGui::BeginTabItem( "Tests" ) )
465+
if ( ImGui::BeginTabItem( "Samples" ) )
466466
{
467467
int categoryIndex = 0;
468468
const char* category = g_sampleEntries[categoryIndex].category;
@@ -538,7 +538,7 @@ int main( int, char** )
538538

539539
s_settings.Load();
540540
s_settings.workerCount = b2MinInt( 8, (int)enki::GetNumHardwareThreads() / 2 );
541-
SortTests();
541+
SortSamples();
542542

543543
glfwSetErrorCallback( glfwErrorCallback );
544544

0 commit comments

Comments
 (0)