载入中...
搜索中...
未找到
World.h
浏览该文件的文档.
1#pragma once
2#include "common/Export.h"
3
4
5#include "common/Snapshot.h"
6#include "common/Result.h"
8#include "physics/Joint2D.h"
10
11#include <cstdint>
12#include <memory>
13#include <string>
14#include <unordered_map>
15#include <unordered_set>
16#include <vector>
17
18class b2World;
19class b2Body;
20class b2Fixture;
21class b2Joint;
22class b2Contact;
23struct b2Manifold;
24struct b2ContactImpulse;
25
26namespace eve::graphics {
27class Graphics;
28}
29
30namespace eve::physics {
31
32class Body;
33class Fixture;
34class ContactRelay;
35class Mechanism2D;
36
42public:
44 struct ContactEvent {
45 int bodyAId = 0;
46 int bodyBId = 0;
47 std::string fixtureATag;
48 std::string fixtureBTag;
49 };
50
52 float pointX = 0.f;
53 float pointY = 0.f;
54 float normalX = 0.f;
55 float normalY = 0.f;
56 float relativeNormalSpeed = 0.f;
57 float normalImpulse = 0.f;
58 float tangentImpulse = 0.f;
59 };
60
65 struct ClothContact {
66 bool hit = false;
67 float nx = 0.f;
68 float ny = 0.f;
69 float depth = 0.f; // radius - distance (pixels); > 0 when inside
70 Body *body = nullptr;
71 };
72
80 World(float gravityX, float gravityY, bool sleep, float meter,
82 ~World();
83
84 World(const World &) = delete;
85 World &operator=(const World &) = delete;
86
88 void update(float dt);
90 void updateFull(float dt, int velocityIterations, int positionIterations);
91
99 [[nodiscard("check the physics step outcome or explicitly ignore it")]]
101
103 [[nodiscard]] SimulationObservation simulationObservation() const noexcept;
105 [[nodiscard]] SimulationBackendKind backendKind() const noexcept;
107 [[nodiscard]] SimulationDeterminism backendDeterminism() const noexcept;
109 [[nodiscard]] eve::SimulationTick simulationTick() const noexcept { return simulationTick_; }
111 [[nodiscard]] PhysicsWorldHandle runtimeHandle() const noexcept { return runtimeHandle_; }
120 [[nodiscard]] std::weak_ptr<const void> lifetimeToken() const noexcept { return lifetime_; }
122 [[nodiscard]] eve::PersistentId persistentId() const noexcept { return instanceId_; }
124 [[nodiscard]] bool usedBackendFallback() const noexcept { return backendFallback_; }
129 [[nodiscard("inspect backend selection diagnostics")]]
130 eve::Status backendSelectionStatus() const;
131
138 [[nodiscard("check or persist the physics snapshot")]]
139 eve::Result<eve::SnapshotEnvelope> snapshot(const eve::SnapshotHashProvider &hashProvider) const;
140
151 [[nodiscard("check the physics snapshot restore outcome")]]
152 eve::Result<void> restore(const eve::SnapshotEnvelope &snapshot, const eve::SnapshotHashProvider &hashProvider);
153
155 void setGravity(float gx, float gy);
156 float getGravityX() const;
157 float getGravityY() const;
158
160 void setMeter(float pixelsPerMeter);
161 float getMeter() const { return meter_; }
162
171 Body *newBody(const std::string &bodyType, float x, float y);
173 [[nodiscard]] Body *findBody(PhysicsBodyHandle handle) const;
175 [[nodiscard]] Body *findBodyById(int bodyId) const;
177 [[nodiscard]] Joint2D *findJoint(PhysicsJointHandle handle) const;
178
189 Joint2D *newDistanceJoint(Body *bodyA, Body *bodyB, float anchorAX, float anchorAY,
190 float anchorBX, float anchorBY, float lengthPixels,
191 bool collideConnected = false);
202 Joint2D *newRevoluteJoint(Body *bodyA, Body *bodyB, float anchorX, float anchorY,
203 bool collideConnected = false);
214 Joint2D *newPrismaticJoint(Body *bodyA, Body *bodyB, float anchorX, float anchorY, float axisX,
215 float axisY, bool collideConnected = false);
226 Joint2D *newWeldJoint(Body *bodyA, Body *bodyB, float anchorX, float anchorY,
227 bool collideConnected = false);
238 Joint2D *newWheelJoint(Body *bodyA, Body *bodyB, float anchorX, float anchorY, float axisX,
239 float axisY, bool collideConnected = false);
250 Joint2D *newMotorJoint(Body *bodyA, Body *bodyB, bool collideConnected = false);
262 Joint2D *newGearJoint(Joint2D *joint1, Joint2D *joint2, float ratio);
263
272 Mechanism2D *newShaft(Body *support, Body *rotor, float anchorX, float anchorY,
273 bool collideConnected = false);
284 Mechanism2D *newRatchet(Body *frame, Body *wheel, float anchorX, float anchorY, int direction,
285 float engagementTorque, bool collideConnected = false);
295 Mechanism2D *newCrankSlider(Body *frame, Body *crank, Body *rod, Body *slider,
296 float crankAnchorX, float crankAnchorY, float crankPinX,
297 float crankPinY, float sliderPinX, float sliderPinY,
298 float slideAxisX, float slideAxisY, bool collideConnected = false);
299
301 void destroyBody(Body *body);
303 void destroy();
304
306 bool isValid() const { return !destroyed_ && world_ != nullptr; }
307
312 bool pointProbe(float x, float y, float radius, ClothContact *out) const;
313
315 void drawDebug(graphics::Graphics *gfx);
316
321 int rayCast(float x1, float y1, float x2, float y2);
322 bool hasRayHit() const { return rayHitBodyId_ >= 0; }
323 int getRayHitBodyId() const { return rayHitBodyId_; }
324 float getRayHitX() const { return rayHitX_; }
325 float getRayHitY() const { return rayHitY_; }
326 float getRayHitNormalX() const { return rayHitNormalX_; }
327 float getRayHitNormalY() const { return rayHitNormalY_; }
329 float getRayHitFraction() const { return rayHitFraction_; }
330
335 int queryAABB(float x, float y, float w, float h);
336 int getQueryCount() const { return static_cast<int>(queryBodyIds_.size()); }
337 int getQueryBodyId(int index) const;
338
339 int getBeginContactCount() const { return int(beginContacts_.size()); }
340 int getBeginContactBodyAId(int index) const;
341 int getBeginContactBodyBId(int index) const;
342 std::string getBeginContactFixtureATag(int index) const;
343 std::string getBeginContactFixtureBTag(int index) const;
344 int getEndContactCount() const { return int(endContacts_.size()); }
345 int getEndContactBodyAId(int index) const;
346 int getEndContactBodyBId(int index) const;
347 std::string getEndContactFixtureATag(int index) const;
348 std::string getEndContactFixtureBTag(int index) const;
349
350 int getImpactCount() const { return int(impacts_.size()); }
351 int getImpactBodyAId(int index) const;
352 int getImpactBodyBId(int index) const;
353 std::string getImpactFixtureATag(int index) const;
354 std::string getImpactFixtureBTag(int index) const;
355 float getImpactPointX(int index) const;
356 float getImpactPointY(int index) const;
357 float getImpactNormalX(int index) const;
358 float getImpactNormalY(int index) const;
359 float getImpactRelativeNormalSpeed(int index) const;
360 float getImpactNormalImpulse(int index) const;
361 float getImpactTangentImpulse(int index) const;
363 void clearContactEvents();
364
366 float toMeters(float pixels) const;
368 float toPixels(float meters) const;
369
378 b2World *raw() { return world_; }
387 const b2World *raw() const { return world_; }
388
389 void onBeginContact(b2Contact *contact);
390 void onEndContact(b2Contact *contact);
391 void onPreSolve(b2Contact *contact, const b2Manifold *oldManifold);
392 void onPostSolve(b2Contact *contact, const b2ContactImpulse *impulse);
393
394 void forgetBody(Body *body);
395 void forgetFixture(Fixture *fixture);
397 void forgetJoint(Joint2D *joint);
399 void forgetMechanism(Mechanism2D *mechanism);
400
401 int nextBodyId();
402 PhysicsBodyHandle nextBodyRuntimeHandle();
404 PhysicsJointHandle nextJointRuntimeHandle();
406 int nextJointId();
408 int nextMechanismId();
409
410private:
411 friend struct WorldSnapshotAccess;
412 friend class Body;
413 friend class Fixture;
414 friend class Joint2D;
415 friend class Mechanism2D;
416
423 Joint2D *adoptJoint(Body *bodyA, Body *bodyB, b2Joint *raw, Joint2D::Kind kind);
424
425 b2World *world_ = nullptr;
426 ContactRelay *relay_ = nullptr;
427 std::unique_ptr<ISimulationBackend> simulation_;
428 PhysicsWorldHandle runtimeHandle_ = PhysicsWorldHandle::invalid();
429 std::shared_ptr<const void> lifetime_ = std::make_shared<int>(0);
431 float meter_ = 30.f;
432 int nextId_ = 1;
433 int nextJointId_ = 1;
434 int nextMechanismId_ = 1;
435 std::uint32_t nextBodyHandleIndex_ = 1u;
436 std::uint32_t nextJointHandleIndex_ = 1u;
437 bool destroyed_ = false;
439 eve::Status backendSelectionStatus_ = eve::Status::success();
440 bool backendFallback_ = false;
441
442 std::unordered_set<Body *> bodies_;
443 std::unordered_set<Fixture *> fixtures_;
444 std::unordered_set<Joint2D *> joints_;
445 std::unordered_set<Mechanism2D *> mechanisms_;
446 std::unordered_map<PhysicsJointHandle, Joint2D *> jointHandles_;
447
448 int rayHitBodyId_ = -1;
449 float rayHitX_ = 0.f;
450 float rayHitY_ = 0.f;
451 float rayHitNormalX_ = 0.f;
452 float rayHitNormalY_ = 0.f;
453 float rayHitFraction_ = 0.f;
454
455 std::vector<int> queryBodyIds_;
456
457 struct PreSolveData {
458 float pointX = 0.f;
459 float pointY = 0.f;
460 float normalX = 0.f;
461 float normalY = 0.f;
462 float relativeNormalSpeed = 0.f;
463 };
464 std::unordered_map<b2Contact *, PreSolveData> preSolve_;
465 std::vector<ContactEvent> beginContacts_;
466 std::vector<ContactEvent> endContacts_;
467 std::vector<ImpactEvent> impacts_;
468
469 [[nodiscard]] eve::Result<void> prepareRuntimeHandleRefresh() const;
470 void refreshRuntimeHandlesAfterRestore();
471 void adoptPreparedTopology(World &prepared);
472};
473
474} // namespace eve::physics
float w
Definition AnimClip.cpp:738
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
float nx
float ny
#define EVENGINE_API_WORLD
Definition Export.h:109
int h
void(* destroy)(void *)
TokenKind kind
Process-local, generation-qualified handles owned by the physics domain.
float radius
bool hit
PrimitiveHandle handle
uint8_t * pixels
Move-only, checked operation results for the common layer.
RoadLaneDirection direction
float axisY
Definition RockMesh.cpp:22
float axisX
Definition RockMesh.cpp:22
Backend-neutral, observable fixed-step contract for physics domains.
Versioned, integrity-checked persistence envelopes.
TerrainThermalSettings settings
float step
Definition TreeMesh.cpp:314
std::string body
uint32_t index
std::uint32_t depth
Move-only operation result carrying either a value or Status.
Definition Result.h:155
Structured status and zero or more diagnostics for an operation.
Definition Status.h:68
static Status success(StatusCode code=StatusCode::Ok)
Construct a successful status with an explicit non-error outcome.
Definition Status.h:81
Id128 public API.
Definition Identity.h:112
static constexpr Id128 nil() noexcept
Returns the all-zero nil value.
Definition Identity.h:142
static constexpr StrongUint64 zero() noexcept
Returns the zero value for this strong type.
2D rigid body (Box2D) in pixel-space coordinates. Owned by a World; create shapes with newRectangleFi...
Definition Body.h:21
2D fixture: a shape attached to a Body with material + filter settings. Also carries a string tag use...
Definition Fixture.h:18
Script-facing Box2D joint owned by a World.
Definition Joint2D.h:21
Kind
Supported joint geometry.
Definition Joint2D.h:27
Composed 2D mechanical assembly owned by a World.
Definition Mechanism2D.h:25
Box2D world wrapper (2D physics) with pixel-space coordinates. Handles stepping, gravity,...
Definition World.h:41
float getRayHitX() const
Definition World.h:324
int getRayHitBodyId() const
Definition World.h:323
std::weak_ptr< const void > lifetimeToken() const noexcept
Weak lifetime token for guarded cross-domain world observers.
Definition World.h:120
float getRayHitY() const
Definition World.h:325
World(const World &)=delete
int getQueryCount() const
Definition World.h:336
eve::PersistentId persistentId() const noexcept
Stable non-nil identity written to snapshot envelopes.
Definition World.h:122
int getImpactCount() const
Definition World.h:350
float getRayHitFraction() const
Fraction along the segment [0,1] of the closest hit.
Definition World.h:329
float getRayHitNormalY() const
Definition World.h:327
bool hasRayHit() const
Definition World.h:322
b2World * raw()
Exposes the underlying Box2D world for tightly-scoped backend integration.
Definition World.h:378
bool usedBackendFallback() const noexcept
Whether optional accelerator selection fell back to CPU.
Definition World.h:124
int getBeginContactCount() const
Definition World.h:339
PhysicsWorldHandle runtimeHandle() const noexcept
Process-local identity used by PhysicsLink; invalid after destruction.
Definition World.h:111
World & operator=(const World &)=delete
float getRayHitNormalX() const
Definition World.h:326
int getEndContactCount() const
Definition World.h:344
const b2World * raw() const
Exposes the underlying Box2D world for read-only backend integration.
Definition World.h:387
bool isValid() const
True while the underlying Box2D world is alive.
Definition World.h:306
float getMeter() const
Definition World.h:161
卡牌游戏 UI 工具模块:工厂 + 脚本绑定入口。 功能参考 ycarowr/UiCard:扇形手牌布局、抽牌/洗牌、悬浮放大、拖拽到落牌区、 敌方手牌(背面/偷看)、费用不足置灰,以及可实时调节的布局...
Definition Animation.h:25
Optional physics backend for vehicle mobility and body attach.
Definition Climbing.h:36
SimulationBackendKind
Kind of implementation that owns a simulation step.
SimulationDeterminism
Determinism guarantee made by a simulation backend.
Build metadata (engine git commit, build time, third-party version).
Definition Build.cpp:16
std::function< Result< ContentId >(std::string_view canonicalInput)> SnapshotHashProvider
Injected content-digest implementation used by snapshots.
Definition Snapshot.h:36
One deterministic fixed-step emitted by SimulationClock.
Definition Time.h:158
Stable outer format shared by persistence and cross-process snapshots.
Definition Snapshot.h:46
Observable backend progress shared by CPU and accelerator providers.
Validated solver policy for one simulation step.
Result of a point probe: deepest non-sensor fixture within radius. Normal points from the shape towar...
Definition World.h:65
ContactEvent public API.
Definition World.h:44