Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bounding box performance experiments #829

Merged
merged 8 commits into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ jobs:
run: ./bin/${{env.BUILD_TYPE}}/test

samples-windows:
name: windows
name: samples-windows
runs-on: windows-latest
steps:

Expand All @@ -102,4 +102,16 @@ jobs:

- name: Build
run: cmake --build ${{github.workspace}}/build --config Release


samples-macos:
name: samples-macos
runs-on: macos-latest

steps:
- uses: actions/checkout@v4

- name: Configure CMake
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=Release -DBOX2D_SAMPLES=ON -DBUILD_SHARED_LIBS=OFF -DBOX2D_UNIT_TESTS=OFF

- name: Build
run: cmake --build ${{github.workspace}}/build --config Release
2 changes: 1 addition & 1 deletion docs/FAQ.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ Box2D also does not have exact collision. There is no continuous collision betwe
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.

### Tile Based Environment
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.
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.

### Asteroid Type Coordinate Systems
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.
Expand Down
14 changes: 8 additions & 6 deletions include/box2d/collision.h
Original file line number Diff line number Diff line change
Expand Up @@ -249,17 +249,17 @@ B2_API bool b2PointInCapsule( b2Vec2 point, const b2Capsule* shape );
/// Test a point for overlap with a convex polygon in local space
B2_API bool b2PointInPolygon( b2Vec2 point, const b2Polygon* shape );

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

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

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

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

/// Shape cast versus a circle. Initial overlap is treated as a miss.
Expand Down Expand Up @@ -348,8 +348,10 @@ typedef struct b2DistanceProxy
float radius;
} b2DistanceProxy;

/// Used to warm start b2Distance. Set count to zero on first call or
/// use zero initialization.
/// Used to warm start the GJK simplex. If you call this function multiple times with nearby
/// transforms this might improve performance. Otherwise you can zero initialize this.
/// The distance cache must be initialized to zero on the first call.
/// Users should generally just zero initialize this structure for each call.
typedef struct b2DistanceCache
{
/// The number of stored simplex points
Expand Down
8 changes: 8 additions & 0 deletions include/box2d/math_functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,9 @@ B2_INLINE b2Rot b2MakeRot( float angle )
return B2_LITERAL( b2Rot ){ cs.cosine, cs.sine };
}

/// Compute the rotation between two unit vectors
B2_API b2Rot b2ComputeRotationBetweenUnitVectors( b2Vec2 v1, b2Vec2 v2 );

/// Is this rotation normalized?
B2_INLINE bool b2IsNormalized( b2Rot q )
{
Expand All @@ -352,6 +355,7 @@ B2_INLINE bool b2IsNormalized( b2Rot q )

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

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

/// Creates a transform that converts a local point in frame B to a local point in frame A.
/// v2 = A.q' * (B.q * v1 + B.p - A.p)
/// = A.q' * B.q * v1 + A.q' * (B.p - A.p)
B2_INLINE b2Transform b2InvMulTransforms( b2Transform A, b2Transform B )
Expand Down
6 changes: 6 additions & 0 deletions include/box2d/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -969,6 +969,9 @@ typedef struct b2SensorBeginTouchEvent
} b2SensorBeginTouchEvent;

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

/// An end touch event is generated when two shapes stop touching.
/// You will not get an end event if you do anything that destroys contacts outside
/// of the world step. These include things like setting the transform, destroying a body
/// or shape, or changing a filter or body type.
typedef struct b2ContactEndTouchEvent
{
/// Id of the first shape
Expand Down
9 changes: 2 additions & 7 deletions samples/draw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -633,11 +633,6 @@ struct GLTriangles
GLint m_projectionUniform;
};

struct Transform
{
float x, y, c, s;
};

struct CircleData
{
b2Vec2 position;
Expand Down Expand Up @@ -781,7 +776,7 @@ struct GLCircles

struct SolidCircleData
{
Transform transform;
b2Transform transform;
float radius;
RGBA8 rgba;
};
Expand Down Expand Up @@ -926,7 +921,7 @@ struct GLSolidCircles

struct CapsuleData
{
Transform transform;
b2Transform transform;
float radius;
float length;
RGBA8 rgba;
Expand Down
6 changes: 3 additions & 3 deletions samples/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ static inline int CompareSamples( const void* a, const void* b )
return result;
}

static void SortTests()
static void SortSamples()
{
qsort( g_sampleEntries, g_sampleCount, sizeof( SampleEntry ), CompareSamples );
}
Expand Down Expand Up @@ -462,7 +462,7 @@ static void UpdateUI()

ImGuiTreeNodeFlags nodeFlags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick;

if ( ImGui::BeginTabItem( "Tests" ) )
if ( ImGui::BeginTabItem( "Samples" ) )
{
int categoryIndex = 0;
const char* category = g_sampleEntries[categoryIndex].category;
Expand Down Expand Up @@ -538,7 +538,7 @@ int main( int, char** )

s_settings.Load();
s_settings.workerCount = b2MinInt( 8, (int)enki::GetNumHardwareThreads() / 2 );
SortTests();
SortSamples();

glfwSetErrorCallback( glfwErrorCallback );

Expand Down
Loading