From f0763aca7d4dfa8f1c19c2c4a9e66fa6e93ea32e Mon Sep 17 00:00:00 2001 From: Erin Catto Date: Thu, 12 Dec 2024 16:45:00 -0800 Subject: [PATCH] Timer update (#856) Faster macos timer Faster linux timer (hopefully works on emscripten) I confirmed these timers are fast Updated M2 MacOS benchmarks Updated N100 Linux benchmarks --- benchmark/m2air_neon/joint_grid.csv | 8 +- benchmark/m2air_neon/large_pyramid.csv | 8 +- benchmark/m2air_neon/many_pyramids.csv | 8 +- benchmark/m2air_neon/rain.csv | 5 + benchmark/m2air_neon/smash.csv | 8 +- benchmark/m2air_neon/spinner.csv | 5 + benchmark/m2air_neon/tumbler.csv | 8 +- benchmark/n100_avx2/joint_grid.csv | 8 +- benchmark/n100_avx2/large_pyramid.csv | 8 +- benchmark/n100_avx2/many_pyramids.csv | 8 +- benchmark/n100_avx2/rain.csv | 5 + benchmark/n100_avx2/smash.csv | 8 +- benchmark/n100_avx2/spinner.csv | 5 + benchmark/n100_avx2/tumbler.csv | 8 +- benchmark/n100_sse2/joint_grid.csv | 8 +- benchmark/n100_sse2/large_pyramid.csv | 8 +- benchmark/n100_sse2/many_pyramids.csv | 8 +- benchmark/n100_sse2/rain.csv | 5 + benchmark/n100_sse2/smash.csv | 8 +- benchmark/n100_sse2/spinner.csv | 5 + benchmark/n100_sse2/tumbler.csv | 8 +- include/box2d/base.h | 8 +- include/box2d/collision.h | 28 ++--- samples/sample_benchmark.cpp | 2 +- samples/sample_collision.cpp | 16 +-- samples/sample_geometry.cpp | 4 +- samples/sample_shapes.cpp | 2 +- samples/sample_stacking.cpp | 2 +- shared/random.c | 2 +- src/aabb.c | 23 ---- src/aabb.h | 2 +- src/broad_phase.c | 12 +- src/distance.c | 6 +- src/dynamic_tree.c | 135 +++------------------ src/geometry.c | 7 +- src/hull.c | 18 +-- src/manifold.c | 4 +- src/shape.h | 3 +- src/solver.c | 6 +- src/timer.c | 158 ++++++------------------- src/world.c | 2 +- 41 files changed, 203 insertions(+), 387 deletions(-) create mode 100644 benchmark/m2air_neon/rain.csv create mode 100644 benchmark/m2air_neon/spinner.csv create mode 100644 benchmark/n100_avx2/rain.csv create mode 100644 benchmark/n100_avx2/spinner.csv create mode 100644 benchmark/n100_sse2/rain.csv create mode 100644 benchmark/n100_sse2/spinner.csv diff --git a/benchmark/m2air_neon/joint_grid.csv b/benchmark/m2air_neon/joint_grid.csv index bde92d859..901334211 100644 --- a/benchmark/m2air_neon/joint_grid.csv +++ b/benchmark/m2air_neon/joint_grid.csv @@ -1,5 +1,5 @@ threads,fps -1,515.583 -2,968.592 -3,1393.95 -4,1652.07 +1,214.889 +2,344.308 +3,499.192 +4,589.811 diff --git a/benchmark/m2air_neon/large_pyramid.csv b/benchmark/m2air_neon/large_pyramid.csv index 3517e4263..fd61f8a03 100644 --- a/benchmark/m2air_neon/large_pyramid.csv +++ b/benchmark/m2air_neon/large_pyramid.csv @@ -1,5 +1,5 @@ threads,fps -1,327.475 -2,606.037 -3,843.779 -4,1057.89 +1,326.445 +2,594.514 +3,826.976 +4,1043.61 diff --git a/benchmark/m2air_neon/many_pyramids.csv b/benchmark/m2air_neon/many_pyramids.csv index 1edc5bc6a..5cb91ef9d 100644 --- a/benchmark/m2air_neon/many_pyramids.csv +++ b/benchmark/m2air_neon/many_pyramids.csv @@ -1,5 +1,5 @@ threads,fps -1,85.4238 -2,159.788 -3,219.475 -4,261.439 +1,85.882 +2,160.755 +3,220.359 +4,266.172 diff --git a/benchmark/m2air_neon/rain.csv b/benchmark/m2air_neon/rain.csv new file mode 100644 index 000000000..21c68872f --- /dev/null +++ b/benchmark/m2air_neon/rain.csv @@ -0,0 +1,5 @@ +threads,fps +1,152.46 +2,253.474 +3,326.158 +4,396.199 diff --git a/benchmark/m2air_neon/smash.csv b/benchmark/m2air_neon/smash.csv index 8bed7f253..b0b3b2496 100644 --- a/benchmark/m2air_neon/smash.csv +++ b/benchmark/m2air_neon/smash.csv @@ -1,5 +1,5 @@ threads,fps -1,166.289 -2,262.228 -3,329.267 -4,393.513 +1,193.98 +2,307.236 +3,386.559 +4,459.442 diff --git a/benchmark/m2air_neon/spinner.csv b/benchmark/m2air_neon/spinner.csv new file mode 100644 index 000000000..17b15199e --- /dev/null +++ b/benchmark/m2air_neon/spinner.csv @@ -0,0 +1,5 @@ +threads,fps +1,312.26 +2,493.611 +3,639.152 +4,780.522 diff --git a/benchmark/m2air_neon/tumbler.csv b/benchmark/m2air_neon/tumbler.csv index e926a1e57..664ad2721 100644 --- a/benchmark/m2air_neon/tumbler.csv +++ b/benchmark/m2air_neon/tumbler.csv @@ -1,5 +1,5 @@ threads,fps -1,351.845 -2,549.496 -3,674.889 -4,801.015 +1,431.639 +2,671.981 +3,818.123 +4,993.461 diff --git a/benchmark/n100_avx2/joint_grid.csv b/benchmark/n100_avx2/joint_grid.csv index c1705932d..f148cb8da 100644 --- a/benchmark/n100_avx2/joint_grid.csv +++ b/benchmark/n100_avx2/joint_grid.csv @@ -1,5 +1,5 @@ threads,fps -1,115.85 -2,209.251 -3,266.537 -4,319.147 +1,75.178 +2,123.214 +3,158.983 +4,182.112 diff --git a/benchmark/n100_avx2/large_pyramid.csv b/benchmark/n100_avx2/large_pyramid.csv index 780619503..8c9833030 100644 --- a/benchmark/n100_avx2/large_pyramid.csv +++ b/benchmark/n100_avx2/large_pyramid.csv @@ -1,5 +1,5 @@ threads,fps -1,133.69 -2,239.395 -3,312.458 -4,360.458 +1,132.297 +2,234.621 +3,308.883 +4,355.701 diff --git a/benchmark/n100_avx2/many_pyramids.csv b/benchmark/n100_avx2/many_pyramids.csv index ca11aef05..8a5f8e574 100644 --- a/benchmark/n100_avx2/many_pyramids.csv +++ b/benchmark/n100_avx2/many_pyramids.csv @@ -1,5 +1,5 @@ threads,fps -1,32.0345 -2,56.8865 -3,71.4046 -4,76.2903 +1,32.0528 +2,56.6901 +3,71.2562 +4,77.5141 diff --git a/benchmark/n100_avx2/rain.csv b/benchmark/n100_avx2/rain.csv new file mode 100644 index 000000000..afa8fbf3b --- /dev/null +++ b/benchmark/n100_avx2/rain.csv @@ -0,0 +1,5 @@ +threads,fps +1,71.7432 +2,117.863 +3,141.721 +4,161.414 diff --git a/benchmark/n100_avx2/smash.csv b/benchmark/n100_avx2/smash.csv index 09be56897..e0b24c430 100644 --- a/benchmark/n100_avx2/smash.csv +++ b/benchmark/n100_avx2/smash.csv @@ -1,5 +1,5 @@ threads,fps -1,73.9639 -2,115.759 -3,138.925 -4,157.394 +1,88.4488 +2,135.265 +3,162.135 +4,184.08 diff --git a/benchmark/n100_avx2/spinner.csv b/benchmark/n100_avx2/spinner.csv new file mode 100644 index 000000000..9d0cdeb8c --- /dev/null +++ b/benchmark/n100_avx2/spinner.csv @@ -0,0 +1,5 @@ +threads,fps +1,159.879 +2,261.516 +3,308.75 +4,360.254 diff --git a/benchmark/n100_avx2/tumbler.csv b/benchmark/n100_avx2/tumbler.csv index 0733d28ef..e64bf4445 100644 --- a/benchmark/n100_avx2/tumbler.csv +++ b/benchmark/n100_avx2/tumbler.csv @@ -1,5 +1,5 @@ threads,fps -1,163.663 -2,261.691 -3,317.057 -4,362.4 +1,205.268 +2,320.216 +3,389.513 +4,449.153 diff --git a/benchmark/n100_sse2/joint_grid.csv b/benchmark/n100_sse2/joint_grid.csv index 6762c872a..2ba1fe9f7 100644 --- a/benchmark/n100_sse2/joint_grid.csv +++ b/benchmark/n100_sse2/joint_grid.csv @@ -1,5 +1,5 @@ threads,fps -1,119.293 -2,213.357 -3,268.455 -4,321.339 +1,75.5947 +2,123.228 +3,160.379 +4,181.545 diff --git a/benchmark/n100_sse2/large_pyramid.csv b/benchmark/n100_sse2/large_pyramid.csv index 67c33d927..727c13349 100644 --- a/benchmark/n100_sse2/large_pyramid.csv +++ b/benchmark/n100_sse2/large_pyramid.csv @@ -1,5 +1,5 @@ threads,fps -1,128.152 -2,229.067 -3,302.297 -4,348.367 +1,127.236 +2,226.291 +3,297.628 +4,345.526 diff --git a/benchmark/n100_sse2/many_pyramids.csv b/benchmark/n100_sse2/many_pyramids.csv index e3703b272..a1a9ffcd3 100644 --- a/benchmark/n100_sse2/many_pyramids.csv +++ b/benchmark/n100_sse2/many_pyramids.csv @@ -1,5 +1,5 @@ threads,fps -1,30.9601 -2,55.0378 -3,69.5563 -4,77.3663 +1,30.8828 +2,55.0462 +3,69.5406 +4,77.7339 diff --git a/benchmark/n100_sse2/rain.csv b/benchmark/n100_sse2/rain.csv new file mode 100644 index 000000000..09b52149c --- /dev/null +++ b/benchmark/n100_sse2/rain.csv @@ -0,0 +1,5 @@ +threads,fps +1,72.2901 +2,118.753 +3,142.61 +4,162.35 diff --git a/benchmark/n100_sse2/smash.csv b/benchmark/n100_sse2/smash.csv index 9c3e0329a..6e3d65d8c 100644 --- a/benchmark/n100_sse2/smash.csv +++ b/benchmark/n100_sse2/smash.csv @@ -1,5 +1,5 @@ threads,fps -1,73.2282 -2,114.239 -3,137.388 -4,156.341 +1,86.2381 +2,132.306 +3,160.725 +4,181.842 diff --git a/benchmark/n100_sse2/spinner.csv b/benchmark/n100_sse2/spinner.csv new file mode 100644 index 000000000..b53b9acd2 --- /dev/null +++ b/benchmark/n100_sse2/spinner.csv @@ -0,0 +1,5 @@ +threads,fps +1,156.855 +2,258.638 +3,303.717 +4,358.492 diff --git a/benchmark/n100_sse2/tumbler.csv b/benchmark/n100_sse2/tumbler.csv index 8e8c31f6c..ff8183b5d 100644 --- a/benchmark/n100_sse2/tumbler.csv +++ b/benchmark/n100_sse2/tumbler.csv @@ -1,5 +1,5 @@ threads,fps -1,161.228 -2,257.781 -3,311.219 -4,356.481 +1,199.492 +2,313.012 +3,381.983 +4,441.825 diff --git a/include/box2d/base.h b/include/box2d/base.h index d431028ca..a92bc3f7f 100644 --- a/include/box2d/base.h +++ b/include/box2d/base.h @@ -115,9 +115,11 @@ typedef struct b2Timer { #if defined( _WIN32 ) int64_t start; -#elif defined( __linux__ ) || defined( __APPLE__ ) || defined( __EMSCRIPTEN__ ) - unsigned long long start_sec; - unsigned long long start_usec; +#elif defined( __linux__ ) || defined( __EMSCRIPTEN__ ) + int64_t tv_sec; + int64_t tv_nsec; +#elif defined( __APPLE__ ) + uint64_t start; #else int32_t dummy; #endif diff --git a/include/box2d/collision.h b/include/box2d/collision.h index 59b49671a..712605498 100644 --- a/include/box2d/collision.h +++ b/include/box2d/collision.h @@ -21,7 +21,7 @@ typedef struct b2Hull b2Hull; /// The maximum number of vertices on a convex polygon. Changing this affects performance even if you /// don't use more vertices. -#define b2_maxPolygonVertices 8 +#define B2_MAX_POLYGON_VERTICES 8 /// Low level ray cast input data typedef struct b2RayCastInput @@ -42,7 +42,7 @@ typedef struct b2RayCastInput typedef struct b2ShapeCastInput { /// A point cloud to cast - b2Vec2 points[b2_maxPolygonVertices]; + b2Vec2 points[B2_MAX_POLYGON_VERTICES]; /// The number of points int32_t count; @@ -115,17 +115,17 @@ typedef struct b2Capsule /// A solid convex polygon. It is assumed that the interior of the polygon is to /// the left of each edge. -/// Polygons have a maximum number of vertices equal to b2_maxPolygonVertices. +/// Polygons have a maximum number of vertices equal to B2_MAX_POLYGON_VERTICES. /// In most cases you should not need many vertices for a convex polygon. /// @warning DO NOT fill this out manually, instead use a helper function like /// b2MakePolygon or b2MakeBox. typedef struct b2Polygon { /// The polygon vertices - b2Vec2 vertices[b2_maxPolygonVertices]; + b2Vec2 vertices[B2_MAX_POLYGON_VERTICES]; /// The outward normal vectors of the polygon sides - b2Vec2 normals[b2_maxPolygonVertices]; + b2Vec2 normals[B2_MAX_POLYGON_VERTICES]; /// The centroid of the polygon b2Vec2 centroid; @@ -273,7 +273,7 @@ B2_API b2CastOutput b2ShapeCastPolygon( const b2ShapeCastInput* input, const b2P typedef struct b2Hull { /// The final points of the hull - b2Vec2 points[b2_maxPolygonVertices]; + b2Vec2 points[B2_MAX_POLYGON_VERTICES]; /// The number of points int32_t count; @@ -284,7 +284,7 @@ typedef struct b2Hull /// - all points very close together /// - all points on a line /// - less than 3 points -/// - more than b2_maxPolygonVertices points +/// - more than B2_MAX_POLYGON_VERTICES points /// This welds close points and removes collinear points. /// @warning Do not modify a hull once it has been computed B2_API b2Hull b2ComputeHull( const b2Vec2* points, int32_t count ); @@ -333,7 +333,7 @@ B2_API b2SegmentDistanceResult b2SegmentDistance( b2Vec2 p1, b2Vec2 q1, b2Vec2 p typedef struct b2DistanceProxy { /// The point cloud - b2Vec2 points[b2_maxPolygonVertices]; + b2Vec2 points[B2_MAX_POLYGON_VERTICES]; /// The number of points int32_t count; @@ -601,21 +601,13 @@ B2_API b2Manifold b2CollideChainSegmentAndPolygon( const b2ChainSegment* segment * A dynamic AABB tree broad-phase, inspired by Nathanael Presson's btDbvt. * A dynamic tree arranges data in a binary tree to accelerate * queries such as AABB queries and ray casts. Leaf nodes are proxies - * with an AABB. These are used to hold a user collision object, such as a reference to a b2Shape. + * with an AABB. These are used to hold a user collision object. * Nodes are pooled and relocatable, so I use node indices rather than pointers. * The dynamic tree is made available for advanced users that would like to use it to organize * spatial game data besides rigid bodies. - * - * @note This is an advanced feature and normally not used by applications directly. * @{ */ -/// The default category bit for a tree proxy. Used for collision filtering. -#define b2_defaultCategoryBits ( 1 ) - -/// Convenience mask bits to use when you don't need collision filtering and just want all results. -#define b2_defaultMaskBits ( UINT64_MAX ) - /// A node in the dynamic tree. This is private data placed here for performance reasons. typedef struct b2TreeNode { @@ -653,7 +645,7 @@ typedef struct b2TreeNode /// The dynamic tree structure. This should be considered private data. /// It is placed here for performance reasons. typedef struct b2DynamicTree -{ +{ /// The tree nodes b2TreeNode* nodes; diff --git a/samples/sample_benchmark.cpp b/samples/sample_benchmark.cpp index 1601edcf9..fc421bb5a 100644 --- a/samples/sample_benchmark.cpp +++ b/samples/sample_benchmark.cpp @@ -1297,7 +1297,7 @@ class BenchmarkCast : public Sample int nodeVisits = 0; int leafVisits = 0; float ms = 0.0f; - int sampleCount = m_origins.size(); + int sampleCount = (int)m_origins.size(); if ( m_queryType == e_rayCast ) { diff --git a/samples/sample_collision.cpp b/samples/sample_collision.cpp index 2b30ca1ee..ecd1a40c7 100644 --- a/samples/sample_collision.cpp +++ b/samples/sample_collision.cpp @@ -554,7 +554,7 @@ class DynamicTree : public Sample p->fatBox.lowerBound = b2Sub( p->box.lowerBound, aabbMargin ); p->fatBox.upperBound = b2Add( p->box.upperBound, aabbMargin ); - p->proxyId = b2DynamicTree_CreateProxy( &m_tree, p->fatBox, b2_defaultCategoryBits, m_proxyCount ); + p->proxyId = b2DynamicTree_CreateProxy( &m_tree, p->fatBox, B2_DEFAULT_CATEGORY_BITS, m_proxyCount ); p->rayStamp = -1; p->queryStamp = -1; p->moved = false; @@ -682,7 +682,7 @@ class DynamicTree : public Sample if ( m_queryDrag ) { b2AABB box = { b2Min( m_startPoint, m_endPoint ), b2Max( m_startPoint, m_endPoint ) }; - b2DynamicTree_Query( &m_tree, box, b2_defaultMaskBits, QueryCallback, this ); + b2DynamicTree_Query( &m_tree, box, B2_DEFAULT_MASK_BITS, QueryCallback, this ); g_draw.DrawAABB( box, b2_colorWhite ); } @@ -693,7 +693,7 @@ class DynamicTree : public Sample if ( m_rayDrag ) { b2RayCastInput input = { m_startPoint, b2Sub( m_endPoint, m_startPoint ), 1.0f }; - b2TreeStats result = b2DynamicTree_RayCast( &m_tree, &input, b2_defaultMaskBits, RayCallback, this ); + b2TreeStats result = b2DynamicTree_RayCast( &m_tree, &input, B2_DEFAULT_MASK_BITS, RayCallback, this ); g_draw.DrawSegment( m_startPoint, m_endPoint, b2_colorWhite ); g_draw.DrawPoint( m_startPoint, 5.0f, b2_colorGreen ); @@ -2162,7 +2162,7 @@ class OverlapWorld : public Sample { b2World_OverlapPolygon( m_worldId, &m_queryBox, transform, b2DefaultQueryFilter(), OverlapWorld::OverlapResultFcn, this ); - b2Vec2 points[b2_maxPolygonVertices] = { 0 }; + b2Vec2 points[B2_MAX_POLYGON_VERTICES] = { 0 }; for ( int i = 0; i < m_queryBox.count; ++i ) { points[i] = b2TransformPoint( transform, m_queryBox.vertices[i] ); @@ -3316,7 +3316,7 @@ class ShapeCast : public Sample output.iterations, output.fraction, distanceOutput.distance ); m_textLine += m_textIncrement; - b2Vec2 vertices[b2_maxPolygonVertices]; + b2Vec2 vertices[B2_MAX_POLYGON_VERTICES]; for ( int i = 0; i < m_countA; ++i ) { @@ -3392,11 +3392,11 @@ class ShapeCast : public Sample g_draw.DrawSegment( m_transformB.p, b2Add( m_transformB.p, m_translationB ), b2_colorGray ); } - b2Vec2 m_vAs[b2_maxPolygonVertices]; + b2Vec2 m_vAs[B2_MAX_POLYGON_VERTICES]; int m_countA; float m_radiusA; - b2Vec2 m_vBs[b2_maxPolygonVertices]; + b2Vec2 m_vBs[B2_MAX_POLYGON_VERTICES]; int m_countB; float m_radiusB; @@ -3497,7 +3497,7 @@ class TimeOfImpact : public Sample // b2_toiMaxRootIters); m_textLine += m_textIncrement; - b2Vec2 vertices[b2_maxPolygonVertices]; + b2Vec2 vertices[B2_MAX_POLYGON_VERTICES]; // Draw A b2Transform transformA = b2GetSweepTransform( &sweepA, 0.0f ); diff --git a/samples/sample_geometry.cpp b/samples/sample_geometry.cpp index 3f73553cf..04b1ce75c 100644 --- a/samples/sample_geometry.cpp +++ b/samples/sample_geometry.cpp @@ -15,7 +15,7 @@ class ConvexHull : public Sample public: enum { - e_count = b2_maxPolygonVertices + e_count = B2_MAX_POLYGON_VERTICES }; explicit ConvexHull( Settings& settings ) @@ -211,7 +211,7 @@ class ConvexHull : public Sample return new ConvexHull( settings ); } - b2Vec2 m_points[b2_maxPolygonVertices]; + b2Vec2 m_points[B2_MAX_POLYGON_VERTICES]; int32_t m_count; int32_t m_generation; bool m_auto; diff --git a/samples/sample_shapes.cpp b/samples/sample_shapes.cpp index a38e41fd2..b63362f63 100644 --- a/samples/sample_shapes.cpp +++ b/samples/sample_shapes.cpp @@ -1390,7 +1390,7 @@ class Explosion : public Sample m_referenceAngle += settings.hertz > 0.0f ? 60.0f * B2_PI / 180.0f / settings.hertz : 0.0f; m_referenceAngle = b2UnwindAngle( m_referenceAngle ); - int count = m_jointIds.size(); + int count = (int)m_jointIds.size(); for ( int i = 0; i < count; ++i ) { b2WeldJoint_SetReferenceAngle( m_jointIds[i], m_referenceAngle ); diff --git a/samples/sample_stacking.cpp b/samples/sample_stacking.cpp index 301180837..461244a87 100644 --- a/samples/sample_stacking.cpp +++ b/samples/sample_stacking.cpp @@ -464,7 +464,7 @@ class CircleStack : public Sample m_events.push_back( { indexA, indexB } ); } - int eventCount = m_events.size(); + int eventCount = (int)m_events.size(); for ( int i = 0; i < eventCount; ++i ) { g_draw.DrawString( 5, m_textLine, "%d, %d", m_events[i].indexA, m_events[i].indexB ); diff --git a/shared/random.c b/shared/random.c index ccffd39bc..1854c4eed 100644 --- a/shared/random.c +++ b/shared/random.c @@ -7,7 +7,7 @@ uint32_t g_seed = RAND_SEED; b2Polygon RandomPolygon( float extent ) { - b2Vec2 points[b2_maxPolygonVertices]; + b2Vec2 points[B2_MAX_POLYGON_VERTICES]; int count = 3 + RandomInt() % 6; for ( int i = 0; i < count; ++i ) { diff --git a/src/aabb.c b/src/aabb.c index 1d58bc489..bfa1e7012 100644 --- a/src/aabb.c +++ b/src/aabb.c @@ -130,26 +130,3 @@ b2CastOutput b2AABB_RayCast( b2AABB a, b2Vec2 p1, b2Vec2 p2 ) output.hit = true; return output; } - -#if 0 -bool b2TestOverlap( const b2Shape* shapeA, int32_t indexA, - const b2Shape* shapeB, int32_t indexB, - b2Transform xfA, b2Transform xfB) -{ - b2DistanceInput input; - input->proxyA.Set(shapeA, indexA); - input->proxyB.Set(shapeB, indexB); - input->transformA = xfA; - input->transformB = xfB; - input->useRadii = true; - - b2DistanceCache cache; - cache.count = 0; - - b2DistanceOutput output; - - b2Distance(&output, &cache, &input); - - return output.distance < 10.0f * b2_epsilon; -} -#endif diff --git a/src/aabb.h b/src/aabb.h index b41f13e96..834c8eaa7 100644 --- a/src/aabb.h +++ b/src/aabb.h @@ -8,7 +8,7 @@ // Ray cast an AABB b2CastOutput b2AABB_RayCast( b2AABB a, b2Vec2 p1, b2Vec2 p2 ); -// Get the perimeter length +// Get surface area of an AABB (the perimeter length) static inline float b2Perimeter( b2AABB a ) { float wx = a.upperBound.x - a.lowerBound.x; diff --git a/src/broad_phase.c b/src/broad_phase.c index 05015641a..d5ee5e3c2 100644 --- a/src/broad_phase.c +++ b/src/broad_phase.c @@ -340,21 +340,21 @@ void b2FindPairsTask( int startIndex, int endIndex, uint32_t threadIndex, void* queryContext.queryShapeIndex = b2DynamicTree_GetUserData( baseTree, proxyId ); // Query trees. Only dynamic proxies collide with kinematic and static proxies. - // Using b2_defaultMaskBits so that b2Filter::groupIndex works. + // Using B2_DEFAULT_MASK_BITS so that b2Filter::groupIndex works. if ( proxyType == b2_dynamicBody ) { - // consider using bits = groupIndex > 0 ? b2_defaultMaskBits : maskBits + // consider using bits = groupIndex > 0 ? B2_DEFAULT_MASK_BITS : maskBits queryContext.queryTreeType = b2_kinematicBody; - b2DynamicTree_Query( bp->trees + b2_kinematicBody, fatAABB, b2_defaultMaskBits, b2PairQueryCallback, &queryContext ); + b2DynamicTree_Query( bp->trees + b2_kinematicBody, fatAABB, B2_DEFAULT_MASK_BITS, b2PairQueryCallback, &queryContext ); queryContext.queryTreeType = b2_staticBody; - b2DynamicTree_Query( bp->trees + b2_staticBody, fatAABB, b2_defaultMaskBits, b2PairQueryCallback, &queryContext ); + b2DynamicTree_Query( bp->trees + b2_staticBody, fatAABB, B2_DEFAULT_MASK_BITS, b2PairQueryCallback, &queryContext ); } // All proxies collide with dynamic proxies - // Using b2_defaultMaskBits so that b2Filter::groupIndex works. + // Using B2_DEFAULT_MASK_BITS so that b2Filter::groupIndex works. queryContext.queryTreeType = b2_dynamicBody; - b2DynamicTree_Query( bp->trees + b2_dynamicBody, fatAABB, b2_defaultMaskBits, b2PairQueryCallback, &queryContext ); + b2DynamicTree_Query( bp->trees + b2_dynamicBody, fatAABB, B2_DEFAULT_MASK_BITS, b2PairQueryCallback, &queryContext ); } b2TracyCZoneEnd( pair_task ); diff --git a/src/distance.c b/src/distance.c index 874691d0b..c9846981e 100644 --- a/src/distance.c +++ b/src/distance.c @@ -109,7 +109,7 @@ b2SegmentDistanceResult b2SegmentDistance( b2Vec2 p1, b2Vec2 q1, b2Vec2 p2, b2Ve // todo try not copying b2DistanceProxy b2MakeProxy( const b2Vec2* vertices, int count, float radius ) { - count = b2MinInt( count, b2_maxPolygonVertices ); + count = b2MinInt( count, B2_MAX_POLYGON_VERTICES ); b2DistanceProxy proxy; for ( int i = 0; i < count; ++i ) { @@ -638,7 +638,7 @@ b2CastOutput b2ShapeCast( const b2ShapeCastPairInput* input ) b2DistanceProxy proxyB; proxyB.count = input->proxyB.count; proxyB.radius = input->proxyB.radius; - B2_ASSERT( proxyB.count <= b2_maxPolygonVertices ); + B2_ASSERT( proxyB.count <= B2_MAX_POLYGON_VERTICES ); for ( int i = 0; i < proxyB.count; ++i ) { @@ -1231,7 +1231,7 @@ b2TOIOutput b2TimeOfImpact( const b2TOIInput* input ) pushBackIterations += 1; - if ( pushBackIterations == b2_maxPolygonVertices ) + if ( pushBackIterations == B2_MAX_POLYGON_VERTICES ) { break; } diff --git a/src/dynamic_tree.c b/src/dynamic_tree.c index 10ff1c896..37f88f596 100644 --- a/src/dynamic_tree.c +++ b/src/dynamic_tree.c @@ -11,11 +11,11 @@ #include #include -#define b2_treeStackSize 1024 +#define B2_TREE_STACK_SIZE 1024 static b2TreeNode b2_defaultTreeNode = { .aabb = { { 0.0f, 0.0f }, { 0.0f, 0.0f } }, - .categoryBits = b2_defaultCategoryBits, + .categoryBits = B2_DEFAULT_CATEGORY_BITS, .parent = B2_NULL_INDEX, .child1 = B2_NULL_INDEX, .child2 = B2_NULL_INDEX, @@ -1019,7 +1019,7 @@ b2TreeStats b2DynamicTree_Query( const b2DynamicTree* tree, b2AABB aabb, uint64_ return result; } - int32_t stack[b2_treeStackSize]; + int32_t stack[B2_TREE_STACK_SIZE]; int32_t stackCount = 0; stack[stackCount++] = tree->root; @@ -1051,8 +1051,8 @@ b2TreeStats b2DynamicTree_Query( const b2DynamicTree* tree, b2AABB aabb, uint64_ } else { - B2_ASSERT( stackCount < b2_treeStackSize - 1 ); - if ( stackCount < b2_treeStackSize - 1 ) + B2_ASSERT( stackCount < B2_TREE_STACK_SIZE - 1 ); + if ( stackCount < B2_TREE_STACK_SIZE - 1 ) { stack[stackCount++] = node->child1; stack[stackCount++] = node->child2; @@ -1064,107 +1064,6 @@ b2TreeStats b2DynamicTree_Query( const b2DynamicTree* tree, b2AABB aabb, uint64_ return result; } -#define B2_DIRK_RECURSE 0 - -#if B2_DIRK_RECURSE == 1 -b2TraversalResult b2DynamicTree_RayCast( const b2DynamicTree* tree, const b2RayCastInput* input, uint64_t maskBits, - b2TreeRayCastCallbackFcn* callback, void* context ) -{ - b2TraversalResult result = { 0 }; - - b2Vec2 p1 = input->origin; - b2Vec2 d = input->translation; - - b2Vec2 r = b2Normalize( d ); - - // v is perpendicular to the segment. - b2Vec2 v = b2CrossSV( 1.0f, r ); - b2Vec2 abs_v = b2Abs( v ); - - // Separating axis for segment (Gino, p80). - // |dot(v, p1 - c)| > dot(|v|, h) - - float maxFraction = input->maxFraction; - - b2Vec2 p2 = b2MulAdd( p1, maxFraction, d ); - - // Build a bounding box for the segment. - b2AABB segmentAABB = { b2Min( p1, p2 ), b2Max( p1, p2 ) }; - - int32_t stack[b2_treeStackSize]; - int32_t stackCount = 0; - int32_t nodeId = tree->root; - - b2RayCastInput subInput = *input; - - while ( true ) - { - const b2TreeNode* node = tree->nodes + nodeId; - result.nodeVisits += 1; - - b2AABB nodeAABB = node->aabb; - - if ( ( node->categoryBits & maskBits ) != 0 && b2AABB_Overlaps( nodeAABB, segmentAABB ) ) - { - // Separating axis for segment (Gino, p80). - // |dot(v, p1 - c)| > dot(|v|, h) - // radius extension is added to the node in this case - b2Vec2 c = b2AABB_Center( nodeAABB ); - b2Vec2 h = b2AABB_Extents( nodeAABB ); - float term1 = b2AbsFloat( b2Dot( v, b2Sub( p1, c ) ) ); - float term2 = b2Dot( abs_v, h ); - if ( term2 >= term1 ) - { - if ( b2IsLeaf( node ) ) - { - subInput.maxFraction = maxFraction; - - float value = callback( &subInput, nodeId, node->userData, context ); - result.leafVisits += 1; - - if ( value == 0.0f ) - { - // The client has terminated the ray cast. - return result; - } - - if ( 0.0f < value && value < maxFraction ) - { - // Update segment bounding box. - maxFraction = value; - p2 = b2MulAdd( p1, maxFraction, d ); - segmentAABB.lowerBound = b2Min( p1, p2 ); - segmentAABB.upperBound = b2Max( p1, p2 ); - } - } - else - { - B2_ASSERT( stackCount < b2_treeStackSize - 1 ); - if ( stackCount < b2_treeStackSize - 1 ) - { - stack[stackCount++] = node->child2; - } - - nodeId = node->child1; - - continue; - } - } - } - - if ( stackCount == 0 ) - { - break; - } - - nodeId = stack[--stackCount]; - } - - return result; -} - -#else - b2TreeStats b2DynamicTree_RayCast( const b2DynamicTree* tree, const b2RayCastInput* input, uint64_t maskBits, b2TreeRayCastCallbackFcn* callback, void* context ) { @@ -1194,7 +1093,7 @@ b2TreeStats b2DynamicTree_RayCast( const b2DynamicTree* tree, const b2RayCastInp // Build a bounding box for the segment. b2AABB segmentAABB = { b2Min( p1, p2 ), b2Max( p1, p2 ) }; - int32_t stack[b2_treeStackSize]; + int32_t stack[B2_TREE_STACK_SIZE]; int32_t stackCount = 0; stack[stackCount++] = tree->root; @@ -1260,8 +1159,8 @@ b2TreeStats b2DynamicTree_RayCast( const b2DynamicTree* tree, const b2RayCastInp } else { - B2_ASSERT( stackCount < b2_treeStackSize - 1 ); - if ( stackCount < b2_treeStackSize - 1 ) + B2_ASSERT( stackCount < B2_TREE_STACK_SIZE - 1 ); + if ( stackCount < B2_TREE_STACK_SIZE - 1 ) { b2Vec2 c1 = b2AABB_Center( nodes[node->child1].aabb ); b2Vec2 c2 = b2AABB_Center( nodes[node->child2].aabb ); @@ -1282,8 +1181,6 @@ b2TreeStats b2DynamicTree_RayCast( const b2DynamicTree* tree, const b2RayCastInp return result; } -#endif - b2TreeStats b2DynamicTree_ShapeCast( const b2DynamicTree* tree, const b2ShapeCastInput* input, uint64_t maskBits, b2TreeShapeCastCallbackFcn* callback, void* context ) { @@ -1329,7 +1226,7 @@ b2TreeStats b2DynamicTree_ShapeCast( const b2DynamicTree* tree, const b2ShapeCas b2ShapeCastInput subInput = *input; const b2TreeNode* nodes = tree->nodes; - int32_t stack[b2_treeStackSize]; + int32_t stack[B2_TREE_STACK_SIZE]; int32_t stackCount = 0; stack[stackCount++] = tree->root; @@ -1387,8 +1284,8 @@ b2TreeStats b2DynamicTree_ShapeCast( const b2DynamicTree* tree, const b2ShapeCas } else { - B2_ASSERT( stackCount < b2_treeStackSize - 1 ); - if ( stackCount < b2_treeStackSize - 1 ) + B2_ASSERT( stackCount < B2_TREE_STACK_SIZE - 1 ); + if ( stackCount < B2_TREE_STACK_SIZE - 1 ) { b2Vec2 c1 = b2AABB_Center( nodes[node->child1].aabb ); b2Vec2 c2 = b2AABB_Center( nodes[node->child2].aabb ); @@ -1724,7 +1621,7 @@ static int32_t b2BuildTree( b2DynamicTree* tree, int32_t leafCount ) #endif // todo large stack item - struct b2RebuildItem stack[b2_treeStackSize]; + struct b2RebuildItem stack[B2_TREE_STACK_SIZE]; int32_t top = 0; stack[0].nodeIndex = b2AllocateNode( tree ); @@ -1826,7 +1723,7 @@ static int32_t b2BuildTree( b2DynamicTree* tree, int32_t leafCount ) else { B2_ASSERT( count > 0 ); - B2_ASSERT( top < b2_treeStackSize ); + B2_ASSERT( top < B2_TREE_STACK_SIZE ); top += 1; struct b2RebuildItem* newItem = stack + top; @@ -1890,7 +1787,7 @@ int32_t b2DynamicTree_Rebuild( b2DynamicTree* tree, bool fullBuild ) } int32_t leafCount = 0; - int32_t stack[b2_treeStackSize]; + int32_t stack[B2_TREE_STACK_SIZE]; int32_t stackCount = 0; int32_t nodeIndex = tree->root; @@ -1934,8 +1831,8 @@ int32_t b2DynamicTree_Rebuild( b2DynamicTree* tree, bool fullBuild ) // Handle children nodeIndex = node->child1; - B2_ASSERT( stackCount < b2_treeStackSize ); - if ( stackCount < b2_treeStackSize ) + B2_ASSERT( stackCount < B2_TREE_STACK_SIZE ); + if ( stackCount < B2_TREE_STACK_SIZE ) { stack[stackCount++] = node->child2; } diff --git a/src/geometry.c b/src/geometry.c index 5f450f75c..712656be8 100644 --- a/src/geometry.c +++ b/src/geometry.c @@ -1,8 +1,7 @@ // SPDX-FileCopyrightText: 2023 Erin Catto // SPDX-License-Identifier: MIT -#include "aabb.h" -#include "core.h" +#include "constants.h" #include "shape.h" #include "box2d/collision.h" @@ -11,7 +10,7 @@ #include #include -_Static_assert( b2_maxPolygonVertices > 2, "must be 3 or more" ); +_Static_assert( B2_MAX_POLYGON_VERTICES > 2, "must be 3 or more" ); bool b2IsValidRay( const b2RayCastInput* input ) { @@ -319,7 +318,7 @@ b2MassData b2ComputePolygonMass( const b2Polygon* shape, float density ) return b2ComputeCapsuleMass( &capsule, density ); } - b2Vec2 vertices[b2_maxPolygonVertices] = { 0 }; + b2Vec2 vertices[B2_MAX_POLYGON_VERTICES] = { 0 }; int32_t count = shape->count; float radius = shape->radius; diff --git a/src/hull.c b/src/hull.c index a50ba271f..6fe70b0f3 100644 --- a/src/hull.c +++ b/src/hull.c @@ -24,7 +24,7 @@ static b2Hull b2RecurseHull( b2Vec2 p1, b2Vec2 p2, b2Vec2* ps, int count ) b2Vec2 e = b2Normalize( b2Sub( p2, p1 ) ); // discard points left of e and find point furthest to the right of e - b2Vec2 rightPoints[b2_maxPolygonVertices]; + b2Vec2 rightPoints[B2_MAX_POLYGON_VERTICES]; int rightCount = 0; int bestIndex = 0; @@ -75,7 +75,7 @@ static b2Hull b2RecurseHull( b2Vec2 p1, b2Vec2 p2, b2Vec2* ps, int count ) hull.points[hull.count++] = hull2.points[i]; } - B2_ASSERT( hull.count < b2_maxPolygonVertices ); + B2_ASSERT( hull.count < B2_MAX_POLYGON_VERTICES ); return hull; } @@ -89,19 +89,19 @@ b2Hull b2ComputeHull( const b2Vec2* points, int count ) b2Hull hull; hull.count = 0; - if ( count < 3 || count > b2_maxPolygonVertices ) + if ( count < 3 || count > B2_MAX_POLYGON_VERTICES ) { // check your data return hull; } - count = b2MinInt( count, b2_maxPolygonVertices ); + count = b2MinInt( count, B2_MAX_POLYGON_VERTICES ); b2AABB aabb = { { FLT_MAX, FLT_MAX }, { -FLT_MAX, -FLT_MAX } }; // Perform aggressive point welding. First point always remains. // Also compute the bounding box for later. - b2Vec2 ps[b2_maxPolygonVertices]; + b2Vec2 ps[B2_MAX_POLYGON_VERTICES]; int n = 0; const float linearSlop = b2_linearSlop; const float tolSqr = 16.0f * linearSlop * linearSlop; @@ -174,10 +174,10 @@ b2Hull b2ComputeHull( const b2Vec2* points, int count ) n = n - 1; // split the points into points that are left and right of the line p1-p2. - b2Vec2 rightPoints[b2_maxPolygonVertices - 2]; + b2Vec2 rightPoints[B2_MAX_POLYGON_VERTICES - 2]; int rightCount = 0; - b2Vec2 leftPoints[b2_maxPolygonVertices - 2]; + b2Vec2 leftPoints[B2_MAX_POLYGON_VERTICES - 2]; int leftCount = 0; b2Vec2 e = b2Normalize( b2Sub( p2, p1 ) ); @@ -222,7 +222,7 @@ b2Hull b2ComputeHull( const b2Vec2* points, int count ) hull.points[hull.count++] = hull2.points[i]; } - B2_ASSERT( hull.count <= b2_maxPolygonVertices ); + B2_ASSERT( hull.count <= B2_MAX_POLYGON_VERTICES ); // merge collinear bool searching = true; @@ -272,7 +272,7 @@ b2Hull b2ComputeHull( const b2Vec2* points, int count ) bool b2ValidateHull( const b2Hull* hull ) { - if ( hull->count < 3 || b2_maxPolygonVertices < hull->count ) + if ( hull->count < 3 || B2_MAX_POLYGON_VERTICES < hull->count ) { return false; } diff --git a/src/manifold.c b/src/manifold.c index ecd2d2408..9927158de 100644 --- a/src/manifold.c +++ b/src/manifold.c @@ -1257,8 +1257,8 @@ b2Manifold b2CollideChainSegmentAndPolygon( const b2ChainSegment* segmentA, b2Tr // Get polygonB in frameA int32_t count = polygonB->count; - b2Vec2 vertices[b2_maxPolygonVertices]; - b2Vec2 normals[b2_maxPolygonVertices]; + b2Vec2 vertices[B2_MAX_POLYGON_VERTICES]; + b2Vec2 normals[B2_MAX_POLYGON_VERTICES]; for ( int32_t i = 0; i < count; ++i ) { vertices[i] = b2TransformPoint( xf, polygonB->vertices[i] ); diff --git a/src/shape.h b/src/shape.h index 0b2051ab4..0a6983535 100644 --- a/src/shape.h +++ b/src/shape.h @@ -3,12 +3,11 @@ #pragma once -#include "world.h" +#include "array.h" #include "box2d/types.h" typedef struct b2BroadPhase b2BroadPhase; -typedef struct b2World b2World; typedef struct b2Shape { diff --git a/src/solver.c b/src/solver.c index 17848488e..71da07c0e 100644 --- a/src/solver.c +++ b/src/solver.c @@ -393,12 +393,12 @@ static void b2SolveContinuous( b2World* world, int bodySimIndex ) continue; } - b2DynamicTree_Query( staticTree, box, b2_defaultMaskBits, b2ContinuousQueryCallback, &context ); + b2DynamicTree_Query( staticTree, box, B2_DEFAULT_MASK_BITS, b2ContinuousQueryCallback, &context ); if ( isBullet ) { - b2DynamicTree_Query( kinematicTree, box, b2_defaultMaskBits, b2ContinuousQueryCallback, &context ); - b2DynamicTree_Query( dynamicTree, box, b2_defaultMaskBits, b2ContinuousQueryCallback, &context ); + b2DynamicTree_Query( kinematicTree, box, B2_DEFAULT_MASK_BITS, b2ContinuousQueryCallback, &context ); + b2DynamicTree_Query( dynamicTree, box, B2_DEFAULT_MASK_BITS, b2ContinuousQueryCallback, &context ); } } diff --git a/src/timer.c b/src/timer.c index 82475f708..caff728c7 100644 --- a/src/timer.c +++ b/src/timer.c @@ -79,77 +79,46 @@ void b2Yield() #elif defined( __linux__ ) || defined( __EMSCRIPTEN__ ) #include -#include #include +// maybe try CLOCK_MONOTONIC_RAW b2Timer b2CreateTimer( void ) { - // todo_erin - - //struct timespec ts; - //clock_gettime( CLOCK_MONOTONIC_RAW, &ts ); - - //struct timespec res; - //clock_getres( CLOCK_MONOTONIC, &res ); - b2Timer timer; - struct timeval t; - gettimeofday( &t, 0 ); - timer.start_sec = t.tv_sec; - timer.start_usec = t.tv_usec; + struct timespec ts; + clock_gettime( CLOCK_MONOTONIC, &ts ); + timer.tv_sec = ts.tv_sec; + timer.tv_nsec = ts.tv_nsec; return timer; } float b2GetMilliseconds( const b2Timer* timer ) { - struct timeval t; - gettimeofday( &t, 0 ); - time_t start_sec = timer->start_sec; - suseconds_t start_usec = (suseconds_t)timer->start_usec; + struct timespec ts; + clock_gettime( CLOCK_MONOTONIC, &ts ); + time_t start_sec = timer->tv_sec; + long start_nsec = timer->tv_nsec; - // http://www.gnu.org/software/libc/manual/html_node/Elapsed-Time.html - if ( t.tv_usec < start_usec ) - { - int nsec = ( start_usec - t.tv_usec ) / 1000000 + 1; - start_usec -= 1000000 * nsec; - start_sec += nsec; - } + time_t sec_diff = ts.tv_sec - start_sec; + long nsec_diff = ts.tv_nsec - start_nsec; - if ( t.tv_usec - start_usec > 1000000 ) - { - int nsec = ( t.tv_usec - start_usec ) / 1000000; - start_usec += 1000000 * nsec; - start_sec -= nsec; - } - return 1000.0f * ( t.tv_sec - start_sec ) + 0.001f * ( t.tv_usec - start_usec ); + return (float)( sec_diff * 1000.0 + nsec_diff / 1000000.0 ); } float b2GetMillisecondsAndReset( b2Timer* timer ) { - struct timeval t; - gettimeofday( &t, 0 ); - time_t start_sec = timer->start_sec; - suseconds_t start_usec = (suseconds_t)timer->start_usec; - - // http://www.gnu.org/software/libc/manual/html_node/Elapsed-Time.html - if ( t.tv_usec < start_usec ) - { - int nsec = ( start_usec - t.tv_usec ) / 1000000 + 1; - start_usec -= 1000000 * nsec; - start_sec += nsec; - } + struct timespec ts; + clock_gettime( CLOCK_MONOTONIC, &ts ); + time_t start_sec = timer->tv_sec; + long start_nsec = timer->tv_nsec; - if ( t.tv_usec - start_usec > 1000000 ) - { - int nsec = ( t.tv_usec - start_usec ) / 1000000; - start_usec += 1000000 * nsec; - start_sec -= nsec; - } + time_t sec_diff = ts.tv_sec - start_sec; + long nsec_diff = ts.tv_nsec - start_nsec; - timer->start_sec = t.tv_sec; - timer->start_usec = t.tv_usec; + timer->tv_sec = ts.tv_sec; + timer->tv_nsec = ts.tv_nsec; - return 1000.0f * ( t.tv_sec - start_sec ) + 0.001f * ( t.tv_usec - start_usec ); + return (float)( sec_diff * 1000.0 + nsec_diff / 1000000.0 ); } void b2SleepMilliseconds( int milliseconds ) @@ -167,90 +136,41 @@ void b2Yield() #elif defined( __APPLE__ ) +#include #include #include -#include -//#include +static double s_invFrequency = 0.0; b2Timer b2CreateTimer( void ) { - // todo_erin - //#include - - //// Get current time - //uint64_t start = mach_absolute_time(); - - //// To convert to nanoseconds, you'll need to use mach_timebase_info - //mach_timebase_info_data_t timebase; - //mach_timebase_info( &timebase ); - - //// Convert to nanoseconds - //uint64_t elapsed_ns = ( start * timebase.numer ) / timebase.denom; + if (s_invFrequency == 0) + { + mach_timebase_info_data_t timebase; + mach_timebase_info( &timebase ); - //mach_timebase_info_data_t timebase; - //mach_timebase_info( &timebase ); - //// timebase.numer and timebase.denom can be used to calculate frequency - //// Specifically, frequency = 1e9 / (timebase.numer / timebase.denom) + // convert to ns then to ms + s_invFrequency = 1e-6 * (double)timebase.numer / (double)timebase.denom; + } - b2Timer timer; - struct timeval t; - gettimeofday( &t, 0 ); - timer.start_sec = t.tv_sec; - timer.start_usec = t.tv_usec; + uint64_t start = mach_absolute_time(); + b2Timer timer = { start }; return timer; } float b2GetMilliseconds( const b2Timer* timer ) { - struct timeval t; - gettimeofday( &t, 0 ); - time_t start_sec = timer->start_sec; - suseconds_t start_usec = (suseconds_t)timer->start_usec; - - // http://www.gnu.org/software/libc/manual/html_node/Elapsed-Time.html - if ( t.tv_usec < start_usec ) - { - int nsec = ( start_usec - t.tv_usec ) / 1000000 + 1; - start_usec -= 1000000 * nsec; - start_sec += nsec; - } - - if ( t.tv_usec - start_usec > 1000000 ) - { - int nsec = ( t.tv_usec - start_usec ) / 1000000; - start_usec += 1000000 * nsec; - start_sec -= nsec; - } - return 1000.0f * ( t.tv_sec - start_sec ) + 0.001f * ( t.tv_usec - start_usec ); + uint64_t count = mach_absolute_time(); + float ms = (float)( s_invFrequency * ( count - timer->start ) ); + return ms; } float b2GetMillisecondsAndReset( b2Timer* timer ) { - struct timeval t; - gettimeofday( &t, 0 ); - time_t start_sec = timer->start_sec; - suseconds_t start_usec = (suseconds_t)timer->start_usec; - - // http://www.gnu.org/software/libc/manual/html_node/Elapsed-Time.html - if ( t.tv_usec < start_usec ) - { - int nsec = ( start_usec - t.tv_usec ) / 1000000 + 1; - start_usec -= 1000000 * nsec; - start_sec += nsec; - } - - if ( t.tv_usec - start_usec > 1000000 ) - { - int nsec = ( t.tv_usec - start_usec ) / 1000000; - start_usec += 1000000 * nsec; - start_sec -= nsec; - } - - timer->start_sec = t.tv_sec; - timer->start_usec = t.tv_usec; - - return 1000.0f * ( t.tv_sec - start_sec ) + 0.001f * ( t.tv_usec - start_usec ); + uint64_t count = mach_absolute_time(); + float ms = (float)( s_invFrequency * ( count - timer->start ) ); + timer->start = count; + return ms; } void b2SleepMilliseconds( int milliseconds ) diff --git a/src/world.c b/src/world.c index 436a2d32c..b471178a2 100644 --- a/src/world.c +++ b/src/world.c @@ -970,7 +970,7 @@ static void b2DrawWithBounds( b2World* world, b2DebugDraw* draw ) for ( int i = 0; i < b2_bodyTypeCount; ++i ) { - b2DynamicTree_Query( world->broadPhase.trees + i, draw->drawingBounds, b2_defaultMaskBits, DrawQueryCallback, + b2DynamicTree_Query( world->broadPhase.trees + i, draw->drawingBounds, B2_DEFAULT_MASK_BITS, DrawQueryCallback, &drawContext ); }