8#include <Box2D/Box2D.h>
17b2BodyType parseBodyType(
const std::string &
type) {
18 if (
type ==
"static")
return b2_staticBody;
19 if (
type ==
"kinematic")
return b2_kinematicBody;
20 if (
type ==
"dynamic")
return b2_dynamicBody;
24const char *bodyTypeName(b2BodyType
t) {
26 case b2_staticBody:
return "static";
27 case b2_kinematicBody:
return "kinematic";
28 case b2_dynamicBody:
return "dynamic";
29 default:
return "static";
36 : world_(
world), body_(
body), id_(
id), runtimeHandle_(runtimeHandle) {}
39 if (body_ && world_ && world_->
raw()) {
40 std::vector<Joint2D *> joints(world_->joints_.begin(), world_->joints_.end());
42 if (joint && joint->isValid() && (joint->bodyA_ ==
this || joint->bodyB_ ==
this))
46 b2Fixture *
f = body_->GetFixtureList();
48 b2Fixture *next =
f->GetNext();
49 auto *wrap =
static_cast<Fixture *
>(
f->GetUserData());
56 body_->SetUserData(
nullptr);
57 world_->
raw()->DestroyBody(body_);
66 if (body_) body_->SetUserData(
nullptr);
73 if (!body_ || !world_ || !world_->
raw()) {
77 std::vector<Joint2D *> joints(world_->joints_.begin(), world_->joints_.end());
79 if (joint && joint->isValid() && (joint->bodyA_ ==
this || joint->bodyB_ ==
this))
82 b2Fixture *
f = body_->GetFixtureList();
84 b2Fixture *next =
f->GetNext();
85 auto *wrap =
static_cast<Fixture *
>(
f->GetUserData());
92 body_->SetUserData(
nullptr);
93 world_->
raw()->DestroyBody(body_);
101 if (!body_ || !world_)
return;
102 body_->SetTransform(b2Vec2(world_->
toMeters(
x), world_->
toMeters(
y)), body_->GetAngle());
106 if (!body_ || !world_)
return 0.f;
107 return world_->
toPixels(body_->GetPosition().x);
111 if (!body_ || !world_)
return 0.f;
112 return world_->
toPixels(body_->GetPosition().y);
117 body_->SetTransform(body_->GetPosition(), radians);
121 if (!body_)
return 0.f;
122 return body_->GetAngle();
126 if (!body_ || !world_)
return;
131 if (!body_ || !world_)
return 0.f;
132 return world_->
toPixels(body_->GetLinearVelocity().x);
136 if (!body_ || !world_)
return 0.f;
137 return world_->
toPixels(body_->GetLinearVelocity().y);
141 if (!body_ || !world_)
return 0.f;
142 return world_->
toPixels(body_->GetLinearVelocity().Length());
148 if (!body_ || !world_)
return 0.f;
149 return world_->
toPixels(body_->GetWorldCenter().x);
153 if (!body_ || !world_)
return 0.f;
154 return world_->
toPixels(body_->GetWorldCenter().y);
159 body_->SetAngularVelocity(omega);
163 if (!body_)
return 0.f;
164 return body_->GetAngularVelocity();
168 if (!body_ || !world_)
return;
170 body_->ApplyForceToCenter(b2Vec2(world_->
toMeters(fx), world_->
toMeters(fy)),
true);
174 if (!body_ || !world_)
return;
180 if (!body_ || !world_)
return;
181 body_->ApplyLinearImpulse(b2Vec2(world_->
toMeters(ix), world_->
toMeters(iy)),
182 body_->GetWorldCenter(),
true);
187 body_->ApplyAngularImpulse(impulse,
true);
192 body_->SetType(parseBodyType(bodyType));
196 if (!body_)
return "static";
197 return bodyTypeName(body_->GetType());
202 body_->SetFixedRotation(fixed);
223 body_->SetAwake(
awake);
234 float density,
float friction,
float restitution) {
235 if (!body_ || !world_)
throw eve::Exception(
"Body.newRectangleFixture: body destroyed");
237 throw eve::Exception(
"Body.newRectangleFixture: width/height must be > 0");
239 b2PolygonShape
shape;
245 def.density = density;
246 def.friction = friction;
249 b2Fixture *
raw = body_->CreateFixture(&def);
251 raw->SetUserData(fx);
252 world_->fixtures_.insert(fx);
257 if (!body_ || !world_)
throw eve::Exception(
"Body.newCircleFixture: body destroyed");
265 def.density = density;
266 def.friction = friction;
269 b2Fixture *
raw = body_->CreateFixture(&def);
271 raw->SetUserData(fx);
272 world_->fixtures_.insert(fx);
278 if (!body_ || !world_)
throw eve::Exception(
"Body.newPolygonFixture: body destroyed");
280 throw eve::Exception(
"Body.newPolygonFixture: expected 3..8 packed XY vertices");
281 std::vector<b2Vec2>
points;
285 throw eve::Exception(
"Body.newPolygonFixture: vertices must be finite");
288 b2PolygonShape
shape;
290 if (
shape.GetVertexCount() < 3)
291 throw eve::Exception(
"Body.newPolygonFixture: vertices do not form a convex polygon");
294 def.density = density;
295 def.friction = friction;
297 b2Fixture *
raw = body_->CreateFixture(&def);
298 if (!
raw)
throw eve::Exception(
"Body.newPolygonFixture: Box2D rejected the fixture");
299 auto *fixture =
new Fixture(world_,
this,
raw);
300 raw->SetUserData(fixture);
301 world_->fixtures_.insert(fixture);
307 if (!body_ || !world_)
throw eve::Exception(
"Body.newChainFixture: body destroyed");
310 throw eve::Exception(
"Body.newChainFixture: invalid packed XY vertex count");
311 std::vector<b2Vec2>
points;
315 throw eve::Exception(
"Body.newChainFixture: vertices must be finite");
318 throw eve::Exception(
"Body.newChainFixture: consecutive vertices must be distinct");
322 throw eve::Exception(
"Body.newChainFixture: loop endpoint is implicit and must not be repeated");
330 def.friction = friction;
332 b2Fixture *
raw = body_->CreateFixture(&def);
333 if (!
raw)
throw eve::Exception(
"Body.newChainFixture: Box2D rejected the fixture");
334 auto *fixture =
new Fixture(world_,
this,
raw);
335 raw->SetUserData(fixture);
336 world_->fixtures_.insert(fixture);
std::vector< Point > vertices
std::shared_ptr< const std::vector< glm::vec2 > > points
EVENGINE_API_FOUNDATION public API.
static constexpr RuntimeHandle invalid() noexcept
Returns the canonical invalid handle.
Fixture * newRectangleFixture(float width, float height, float density=1.f, float friction=0.2f, float restitution=0.f)
Creates a rectangle fixture in pixel-space units.
float getLinearVelocityX() const
Returns the linear velocity x.
void applyForceAt(float fx, float fy, float x, float y)
Force applied at a world pixel position.
void setBullet(bool bullet)
CCD bullet mode (recommended for fast small bodies).
float getX() const
Returns the x.
void setAwake(bool awake)
Wakes / sleeps the body manually.
void setType(const std::string &bodyType)
"static" | "kinematic" | "dynamic".
void setAngle(float radians)
Rotation in radians.
float getLinearVelocityY() const
Returns the linear velocity y.
bool isActive() const
True when active.
void applyLinearImpulse(float ix, float iy)
Instantaneous linear impulse.
Fixture * newPolygonFixture(const std::vector< float > &vertices, float density=1.f, float friction=0.2f, float restitution=0.f)
Create a bounded convex polygon fixture from packed local pixel-space XY vertices.
Fixture * newCircleFixture(float radius, float density=1.f, float friction=0.2f, float restitution=0.f)
Creates a circular fixture in pixel-space units.
void setFixedRotation(bool fixed)
Locks rotation so the body cannot spin.
Fixture * newChainFixture(const std::vector< float > &vertices, bool loop=false, float friction=0.2f, float restitution=0.f)
Create an open chain or closed loop from packed local pixel-space XY vertices.
void applyForce(float fx, float fy)
Force (pixels/s² * kg) applied at the center of mass.
bool isAwake() const
True when awake.
bool isFixedRotation() const
True when fixed rotation.
bool isBullet() const
True when bullet.
void setAngularVelocity(float omega)
Angular velocity in radians/s.
b2Body * raw()
Exposes the underlying Box2D body for tightly-scoped backend integration.
float getAngularVelocity() const
Returns the angular velocity.
void destroy()
Destroys the body inside its world.
void applyAngularImpulse(float impulse)
Instantaneous angular impulse.
float getWorldCenterY() const
Returns the world center y.
float getLinearSpeed() const
Magnitude of the linear velocity.
float getAngle() const
Returns the angle.
std::string getType() const
Returns the type.
void invalidate()
Internal: marks the wrapper invalid after world destruction.
void setPosition(float x, float y)
Position in pixels.
float getWorldCenterX() const
World center of mass in pixels.
Body(World *world, b2Body *body, int id, PhysicsBodyHandle runtimeHandle)
Internal: wraps a Box2D body (use World::newBody).
Fixture * newRectangleFixtureAt(float width, float height, float offsetX, float offsetY, float density=1.f, float friction=0.2f, float restitution=0.f)
Creates an offset rectangle fixture in pixel-space units.
float getMass() const
Mass in kilograms (Box2D units).
void setActive(bool active)
Disables/enables the body and its fixtures.
void setLinearVelocity(float vx, float vy)
Linear velocity in pixels/s.
float getY() const
Returns the y.
2D fixture: a shape attached to a Body with material + filter settings. Also carries a string tag use...
Script-facing Box2D joint owned by a World.
Box2D world wrapper (2D physics) with pixel-space coordinates. Handles stepping, gravity,...
void forgetBody(Body *body)
void forgetFixture(Fixture *fixture)
float toPixels(float meters) const
Converts a meter-space length to pixels.
b2World * raw()
Exposes the underlying Box2D world for tightly-scoped backend integration.
float toMeters(float pixels) const
Converts a pixel-space length to meters.
Optional physics backend for vehicle mobility and body attach.