diff --git a/docs/hello.md b/docs/hello.md index b64e777c..4a0a3659 100644 --- a/docs/hello.md +++ b/docs/hello.md @@ -226,8 +226,8 @@ for (int i = 0; i < 90; ++i) { b2World_Step(worldId, timeStep, subStepCount); b2Vec2 position = b2Body_GetPosition(bodyId); - float angle = b2Body_GetAngle(bodyId); - printf("%4.2f %4.2f %4.2f\n", position.x, position.y, angle); + b2Rot rotation = b2Body_GetRot(bodyId); + printf("%4.2f %4.2f %4.2f\n", position.x, position.y, b2Rot_GetAngle(rotation)); } ``` diff --git a/docs/simulation.md b/docs/simulation.md index c27ab827..3e6e9f61 100644 --- a/docs/simulation.md +++ b/docs/simulation.md @@ -506,11 +506,11 @@ simulate movement. Keep in mind that the Box2D interface uses *radians*. ```c -b2Body_SetTransform(myBodyId, position, angleInRadians); +b2Body_SetTransform(myBodyId, position, rotation); b2Transform transform = b2Body_GetTransform(myBodyId); b2Vec2 position = b2Body_GetPosition(myBodyId); b2Rot rotation = b2Body_GetRotation(myBodyId); -float angleInRadians = b2Body_GetAngle(myBodyId); +float angleInRadians = b2Rot_GetAngle(rotation); ``` You can access the center of mass position in local and world diff --git a/include/box2d/box2d.h b/include/box2d/box2d.h index 93a4f441..560e8444 100644 --- a/include/box2d/box2d.h +++ b/include/box2d/box2d.h @@ -200,16 +200,13 @@ B2_API b2Vec2 b2Body_GetPosition(b2BodyId bodyId); /// Get the world rotation of a body as a cosine/sine pair (complex number) B2_API b2Rot b2Body_GetRotation(b2BodyId bodyId); -/// Get the body angle in radians in the range [-pi, pi] -B2_API float b2Body_GetAngle(b2BodyId bodyId); - /// Get the world transform of a body. B2_API b2Transform b2Body_GetTransform(b2BodyId bodyId); /// Set the world transform of a body. This acts as a teleport and is fairly expensive. /// @note Generally you should create a body with then intended transform. /// @see b2BodyDef::position and b2BodyDef::angle -B2_API void b2Body_SetTransform(b2BodyId bodyId, b2Vec2 position, float angle); +B2_API void b2Body_SetTransform(b2BodyId bodyId, b2Vec2 position, b2Rot rotation); /// Get a local point on a body given a world point B2_API b2Vec2 b2Body_GetLocalPoint(b2BodyId bodyId, b2Vec2 worldPoint); diff --git a/include/box2d/math_functions.h b/include/box2d/math_functions.h index 4cb51d30..9177e2ee 100644 --- a/include/box2d/math_functions.h +++ b/include/box2d/math_functions.h @@ -262,7 +262,7 @@ B2_INLINE float b2DistanceSquared(b2Vec2 a, b2Vec2 b) return c.x * c.x + c.y * c.y; } -/// Set using an angle in radians +/// Make a rotation using an angle in radians B2_INLINE b2Rot b2MakeRot(float angle) { // todo determinism @@ -336,7 +336,7 @@ B2_INLINE float b2ComputeAngularVelocity(b2Rot q1, b2Rot q2, float inv_h) return omega; } -/// Get the angle in radians +/// Get the angle in radians in the range [-pi, pi] B2_INLINE float b2Rot_GetAngle(b2Rot q) { // todo determinism diff --git a/include/box2d/types.h b/include/box2d/types.h index 4e973671..5aa94095 100644 --- a/include/box2d/types.h +++ b/include/box2d/types.h @@ -149,8 +149,8 @@ typedef struct b2BodyDef /// if the body is moved after shapes have been added. b2Vec2 position; - /// The initial world angle of the body in radians. - float angle; + /// The initial world rotation of the body. Use b2MakeRot() if you have an angle. + b2Rot rotation; /// The initial linear velocity of the body's origin. Typically in meters per second. b2Vec2 linearVelocity; diff --git a/samples/donut.cpp b/samples/donut.cpp index b66b89bc..80f650db 100644 --- a/samples/donut.cpp +++ b/samples/donut.cpp @@ -51,7 +51,7 @@ void Donut::Spawn(b2WorldId worldId, b2Vec2 position, float scale, int groupInde for (int i = 0; i < e_sides; ++i) { bodyDef.position = {radius * cosf(angle) + center.x, radius * sinf(angle) + center.y}; - bodyDef.angle = angle; + bodyDef.rotation = b2MakeRot(angle); m_bodyIds[i] = b2CreateBody(worldId, &bodyDef); b2CreateCapsuleShape(m_bodyIds[i], &shapeDef, &capsule); diff --git a/samples/sample_bodies.cpp b/samples/sample_bodies.cpp index 2fe1a58a..a85273f2 100644 --- a/samples/sample_bodies.cpp +++ b/samples/sample_bodies.cpp @@ -334,7 +334,7 @@ class Character : public Sample // Chain shape { b2BodyDef bodyDef = b2DefaultBodyDef(); - bodyDef.angle = 0.25f * b2_pi; + bodyDef.rotation = b2MakeRot(0.25f * b2_pi); b2BodyId groundId = b2CreateBody(m_worldId, &bodyDef); b2Vec2 points[4] = {{8.0f, 7.0f}, {7.0f, 8.0f}, {6.0f, 8.0f}, {5.0f, 7.0f}}; @@ -498,7 +498,7 @@ class Weeble : public Sample b2BodyDef bodyDef = b2DefaultBodyDef(); bodyDef.type = b2_dynamicBody; bodyDef.position = {0.0f, 3.0f}; - bodyDef.angle = 0.25f * b2_pi; + bodyDef.rotation = b2MakeRot(0.25f * b2_pi); m_weebleId = b2CreateBody(m_worldId, &bodyDef); b2Capsule capsule = {{0.0f, -1.0f}, {0.0f, 1.0f}, 1.0f}; @@ -531,7 +531,7 @@ class Weeble : public Sample ImGui::Begin("Weeble", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize); if (ImGui::Button("Teleport")) { - b2Body_SetTransform(m_weebleId, {0.0f, 5.0f}, 0.95 * b2_pi); + b2Body_SetTransform(m_weebleId, {0.0f, 5.0f}, b2MakeRot(0.95 * b2_pi)); } if (ImGui::Button("Explode")) @@ -789,7 +789,7 @@ class BadBody : public Sample bodyDef.type = b2_dynamicBody; bodyDef.position = {0.0f, 3.0f}; bodyDef.angularVelocity = 0.2f; - bodyDef.angle = 0.25f * b2_pi; + bodyDef.rotation = b2MakeRot(0.25f * b2_pi); m_badBodyId = b2CreateBody(m_worldId, &bodyDef); @@ -806,7 +806,7 @@ class BadBody : public Sample b2BodyDef bodyDef = b2DefaultBodyDef(); bodyDef.type = b2_dynamicBody; bodyDef.position = {2.0f, 3.0f}; - bodyDef.angle = 0.25f * b2_pi; + bodyDef.rotation = b2MakeRot(0.25f * b2_pi); b2BodyId bodyId = b2CreateBody(m_worldId, &bodyDef); diff --git a/samples/sample_collision.cpp b/samples/sample_collision.cpp index 0b9b34f9..97df0a78 100644 --- a/samples/sample_collision.cpp +++ b/samples/sample_collision.cpp @@ -1469,7 +1469,7 @@ class RayCastWorld : public Sample b2BodyDef bodyDef = b2DefaultBodyDef(); bodyDef.position = {x, y}; - bodyDef.angle = RandomFloat(-b2_pi, b2_pi); + bodyDef.rotation = b2MakeRot(RandomFloat(-b2_pi, b2_pi)); m_bodyIds[m_bodyIndex] = b2CreateBody(m_worldId, &bodyDef); @@ -1954,7 +1954,7 @@ class OverlapWorld : public Sample b2BodyDef bodyDef = b2DefaultBodyDef(); bodyDef.position = {x, y}; - bodyDef.angle = RandomFloat(-b2_pi, b2_pi); + bodyDef.rotation = b2MakeRot(RandomFloat(-b2_pi, b2_pi)); m_bodyIds[m_bodyIndex] = b2CreateBody(m_worldId, &bodyDef); diff --git a/samples/sample_events.cpp b/samples/sample_events.cpp index 605dec2b..e05f8534 100644 --- a/samples/sample_events.cpp +++ b/samples/sample_events.cpp @@ -409,7 +409,7 @@ class ContactEvent : public Sample b2BodyDef bodyDef = b2DefaultBodyDef(); bodyDef.type = b2_dynamicBody; bodyDef.position = {RandomFloat(-38.0f, 38.0f), RandomFloat(-38.0f, 38.0f)}; - bodyDef.angle = RandomFloat(-b2_pi, b2_pi); + bodyDef.rotation = b2MakeRot(RandomFloat(-b2_pi, b2_pi)); bodyDef.linearVelocity = {RandomFloat(-5.0f, 5.0f), RandomFloat(-5.0f, 5.0f)}; bodyDef.angularVelocity = RandomFloat(-1.0f, 1.0f); bodyDef.gravityScale = 0.0f; diff --git a/samples/sample_joints.cpp b/samples/sample_joints.cpp index b265939b..9d96a713 100644 --- a/samples/sample_joints.cpp +++ b/samples/sample_joints.cpp @@ -2259,12 +2259,12 @@ class ScissorLift : public Sample for (int i = 0; i < N; ++i) { bodyDef.position = {0.0f, y}; - bodyDef.angle = 0.15f; + bodyDef.rotation = b2MakeRot(0.15f); b2BodyId bodyId1 = b2CreateBody(m_worldId, &bodyDef); b2CreateCapsuleShape(bodyId1, &shapeDef, &capsule); bodyDef.position = {0.0f, y}; - bodyDef.angle = -0.15f; + bodyDef.rotation = b2MakeRot(-0.15f); b2BodyId bodyId2 = b2CreateBody(m_worldId, &bodyDef); b2CreateCapsuleShape(bodyId2, &shapeDef, &capsule); @@ -2333,7 +2333,7 @@ class ScissorLift : public Sample } bodyDef.position = {0.0f, y}; - bodyDef.angle = 0.0f; + bodyDef.rotation = b2Rot_identity; b2BodyId platformId = b2CreateBody(m_worldId, &bodyDef); b2Polygon box = b2MakeBox(3.0f, 0.2f); diff --git a/samples/sample_shapes.cpp b/samples/sample_shapes.cpp index b2fcf914..48c52b24 100644 --- a/samples/sample_shapes.cpp +++ b/samples/sample_shapes.cpp @@ -329,7 +329,7 @@ class CompoundShapes : public Sample b2BodyDef bodyDef = b2DefaultBodyDef(); bodyDef.type = b2_dynamicBody; bodyDef.position = b2Body_GetPosition(m_table1Id); - bodyDef.angle = b2Body_GetAngle(m_table1Id); + bodyDef.rotation = b2Body_GetRotation(m_table1Id); b2BodyId bodyId = b2CreateBody(m_worldId, &bodyDef); b2ShapeDef shapeDef = b2DefaultShapeDef(); @@ -342,7 +342,7 @@ class CompoundShapes : public Sample b2BodyDef bodyDef = b2DefaultBodyDef(); bodyDef.type = b2_dynamicBody; bodyDef.position = b2Body_GetPosition(m_table2Id); - bodyDef.angle = b2Body_GetAngle(m_table2Id); + bodyDef.rotation = b2Body_GetRotation(m_table2Id); b2BodyId bodyId = b2CreateBody(m_worldId, &bodyDef); b2ShapeDef shapeDef = b2DefaultShapeDef(); @@ -355,7 +355,7 @@ class CompoundShapes : public Sample b2BodyDef bodyDef = b2DefaultBodyDef(); bodyDef.type = b2_dynamicBody; bodyDef.position = b2Body_GetPosition(m_ship1Id); - bodyDef.angle = b2Body_GetAngle(m_ship1Id); + bodyDef.rotation = b2Body_GetRotation(m_ship1Id); // bodyDef.gravityScale = 0.0f; b2BodyId bodyId = b2CreateBody(m_worldId, &bodyDef); @@ -369,7 +369,7 @@ class CompoundShapes : public Sample b2BodyDef bodyDef = b2DefaultBodyDef(); bodyDef.type = b2_dynamicBody; bodyDef.position = b2Body_GetPosition(m_ship2Id); - bodyDef.angle = b2Body_GetAngle(m_ship2Id); + bodyDef.rotation = b2Body_GetRotation(m_ship2Id); // bodyDef.gravityScale = 0.0f; b2BodyId bodyId = b2CreateBody(m_worldId, &bodyDef); diff --git a/samples/sample_stacking.cpp b/samples/sample_stacking.cpp index 1344de7e..cc251969 100644 --- a/samples/sample_stacking.cpp +++ b/samples/sample_stacking.cpp @@ -854,20 +854,20 @@ class CardHouse : public Sample if (i != Nb - 1) { bodyDef.position = {z + 0.25f, y + cardHeight - 0.015f}; - bodyDef.angle = angle2; + bodyDef.rotation = b2MakeRot(angle2); b2BodyId bodyId = b2CreateBody(m_worldId, &bodyDef); b2CreatePolygonShape(bodyId, &shapeDef, &cardBox); } bodyDef.position = {z, y}; - bodyDef.angle = angle1; + bodyDef.rotation = b2MakeRot(angle1); b2BodyId bodyId = b2CreateBody(m_worldId, &bodyDef); b2CreatePolygonShape(bodyId, &shapeDef, &cardBox); z += 0.175f; bodyDef.position = {z, y}; - bodyDef.angle = angle0; + bodyDef.rotation = b2MakeRot(angle0); bodyId = b2CreateBody(m_worldId, &bodyDef); b2CreatePolygonShape(bodyId, &shapeDef, &cardBox); diff --git a/src/body.c b/src/body.c index 0d78aa9a..488b2df4 100644 --- a/src/body.c +++ b/src/body.c @@ -179,7 +179,7 @@ b2BodyId b2CreateBody(b2WorldId worldId, const b2BodyDef* def) { b2CheckDef(def); B2_ASSERT(b2Vec2_IsValid(def->position)); - B2_ASSERT(b2IsValid(def->angle)); + B2_ASSERT(b2Rot_IsValid(def->rotation)); B2_ASSERT(b2Vec2_IsValid(def->linearVelocity)); B2_ASSERT(b2IsValid(def->angularVelocity)); B2_ASSERT(b2IsValid(def->linearDamping) && def->linearDamping >= 0.0f); @@ -236,7 +236,7 @@ b2BodyId b2CreateBody(b2WorldId worldId, const b2BodyDef* def) b2BodySim* bodySim = b2AddBodySim(&set->sims); *bodySim = (b2BodySim){0}; bodySim->transform.p = def->position; - bodySim->transform.q = b2MakeRot(def->angle); + bodySim->transform.q = def->rotation; bodySim->center = def->position; bodySim->rotation0 = bodySim->transform.q; bodySim->center0 = bodySim->center; @@ -633,14 +633,6 @@ b2Rot b2Body_GetRotation(b2BodyId bodyId) return transform.q; } -float b2Body_GetAngle(b2BodyId bodyId) -{ - b2World* world = b2GetWorld(bodyId.world0); - b2Body* body = b2GetBodyFullId(world, bodyId); - b2Transform transform = b2GetBodyTransformQuick(world, body); - return b2Rot_GetAngle(transform.q); -} - b2Transform b2Body_GetTransform(b2BodyId bodyId) { b2World* world = b2GetWorld(bodyId.world0); @@ -680,8 +672,10 @@ b2Vec2 b2Body_GetWorldVector(b2BodyId bodyId, b2Vec2 localVector) return b2RotateVector(transform.q, localVector); } -void b2Body_SetTransform(b2BodyId bodyId, b2Vec2 position, float angle) +void b2Body_SetTransform(b2BodyId bodyId, b2Vec2 position, b2Rot rotation) { + B2_ASSERT(b2Vec2_IsValid(position)); + B2_ASSERT(b2Rot_IsValid(rotation)); B2_ASSERT(b2Body_IsValid(bodyId)); b2World* world = b2GetWorld(bodyId.world0); B2_ASSERT(world->locked == false); @@ -690,7 +684,7 @@ void b2Body_SetTransform(b2BodyId bodyId, b2Vec2 position, float angle) b2BodySim* bodySim = b2GetBodySim(world, body); bodySim->transform.p = position; - bodySim->transform.q = b2MakeRot(angle); + bodySim->transform.q = rotation; bodySim->center = b2TransformPoint(bodySim->transform, bodySim->localCenter); bodySim->rotation0 = bodySim->transform.q; diff --git a/src/types.c b/src/types.c index 943ef31e..514e2428 100644 --- a/src/types.c +++ b/src/types.c @@ -27,6 +27,7 @@ b2BodyDef b2DefaultBodyDef(void) { b2BodyDef def = {0}; def.type = b2_staticBody; + def.rotation = b2Rot_identity; def.sleepThreshold = 0.05f * b2_lengthUnitsPerMeter; def.gravityScale = 1.0f; def.enableSleep = true; diff --git a/test/test_determinism.c b/test/test_determinism.c index a11ae4b8..5688da61 100644 --- a/test/test_determinism.c +++ b/test/test_determinism.c @@ -25,7 +25,7 @@ enum }; b2Vec2 finalPositions[2][e_count]; -float finalAngles[2][e_count]; +b2Rot finalRotations[2][e_count]; typedef struct TaskData { @@ -162,7 +162,7 @@ void TiltedStacks(int testIndex, int workerCount) for (int i = 0; i < e_count; ++i) { finalPositions[testIndex][i] = b2Body_GetPosition(bodies[i]); - finalAngles[testIndex][i] = b2Body_GetAngle(bodies[i]); + finalRotations[testIndex][i] = b2Body_GetRotation(bodies[i]); } b2DestroyWorld(worldId); @@ -189,12 +189,13 @@ int DeterminismTest(void) { b2Vec2 p1 = finalPositions[0][i]; b2Vec2 p2 = finalPositions[1][i]; - float a1 = finalAngles[0][i]; - float a2 = finalAngles[1][i]; + b2Rot rot1 = finalRotations[0][i]; + b2Rot rot2 = finalRotations[1][i]; ENSURE(p1.x == p2.x); ENSURE(p1.y == p2.y); - ENSURE(a1 == a2); + ENSURE(rot1.c == rot2.c); + ENSURE(rot1.s == rot2.s); } return 0; diff --git a/test/test_world.c b/test/test_world.c index 35228807..490e005d 100644 --- a/test/test_world.c +++ b/test/test_world.c @@ -68,7 +68,7 @@ int HelloWorld(void) int subStepCount = 4; b2Vec2 position = b2Body_GetPosition(bodyId); - float angle = b2Body_GetAngle(bodyId); + b2Rot rotation = b2Body_GetRotation(bodyId); // This is our little game loop. for (int i = 0; i < 90; ++i) @@ -79,9 +79,9 @@ int HelloWorld(void) // Now print the position and angle of the body. position = b2Body_GetPosition(bodyId); - angle = b2Body_GetAngle(bodyId); + rotation = b2Body_GetRotation(bodyId); - //printf("%4.2f %4.2f %4.2f\n", position.x, position.y, angle); + //printf("%4.2f %4.2f %4.2f\n", position.x, position.y, b2Rot_GetAngle(rotation)); } // When the world destructor is called, all bodies and joints are freed. This can @@ -90,7 +90,7 @@ int HelloWorld(void) ENSURE(b2AbsFloat(position.x) < 0.01f); ENSURE(b2AbsFloat(position.y - 1.00f) < 0.01f); - ENSURE(b2AbsFloat(angle) < 0.01f); + ENSURE(b2AbsFloat(b2Rot_GetAngle(rotation)) < 0.01f); return 0; }