载入中...
搜索中...
未找到
PhysicsCapabilities.cpp
浏览该文件的文档.
2#include "common/Capability.h"
6#include "physics/Physics.h"
8#include "physics/World.h"
10#include "physics/World3D.h"
11
12#include <algorithm>
13#include <string>
14#include <vector>
15
16namespace eve::physics {
17namespace {
18
19class PhysicsQueryImpl final : public eve::IPhysicsQuery {
20public:
21 int newWorld(float gravityX, float gravityY) override {
22 auto *ph = eve::ModuleManager::getInstance<Physics>("Physics");
23 if (!ph) return -1;
24 auto *w = ph->newWorld(gravityX, gravityY);
25 if (!w) return -1;
26 worlds_.push_back(w);
27 return static_cast<int>(worlds_.size()) - 1;
28 }
29
30 int worldCount() override {
31 int n = 0;
32 for (auto *w : worlds_)
33 if (w) ++n;
34 return n;
35 }
36
37 bool worldGravity(int id, float *gx, float *gy) override {
38 auto *w = world(id);
39 if (!w) return false;
40 if (gx) *gx = w->getGravityX();
41 if (gy) *gy = w->getGravityY();
42 return true;
43 }
44
45 bool rayCast(int id, float x1, float y1, float x2, float y2, RayHitInfo *out) override {
46 auto *w = world(id);
47 if (!w || !out) return false;
48 w->rayCast(x1, y1, x2, y2);
49 out->hit = w->hasRayHit();
50 if (out->hit) {
51 out->bodyId = w->getRayHitBodyId();
52 out->x = w->getRayHitX();
53 out->y = w->getRayHitY();
54 out->normalX = w->getRayHitNormalX();
55 out->normalY = w->getRayHitNormalY();
56 out->fraction = w->getRayHitFraction();
57 }
58 return true;
59 }
60
61 bool removeWorld(int id) override {
62 if (id < 0 || static_cast<size_t>(id) >= worlds_.size()) return false;
63 delete worlds_[static_cast<size_t>(id)];
64 worlds_[static_cast<size_t>(id)] = nullptr;
65 return true;
66 }
67
68private:
69 World *world(int id) const {
70 if (id < 0 || static_cast<size_t>(id) >= worlds_.size()) return nullptr;
71 return worlds_[static_cast<size_t>(id)];
72 }
73
74 std::vector<World *> worlds_;
75};
76
77class CameraObstructionQueryImpl final : public eve::ICameraObstructionQuery {
78public:
79 void add(World3D* world, std::weak_ptr<const void> lifetime) {
80 std::erase_if(worlds_, [](const RegisteredWorld& entry) { return entry.lifetime.expired(); });
81 const auto found = std::find_if(worlds_.begin(), worlds_.end(),
82 [world](const RegisteredWorld& entry) { return entry.world == world; });
83 if (world && found == worlds_.end()) worlds_.push_back({world, std::move(lifetime)});
84 }
85
86 bool sphereCast(float fromX, float fromY, float fromZ, float toX, float toY, float toZ,
87 float radius, uint64_t maskBits, int ignoredBodyId,
88 eve::CameraObstructionHit* out) override {
89 if (out) *out = eve::CameraObstructionHit{};
90 if (!out) return false;
91 for (const RegisteredWorld& entry : worlds_) {
92 auto lifetime = entry.lifetime.lock();
93 World3D* world = entry.world;
94 if (!lifetime || !world || !world->isValid()) continue;
95 CameraSphereHit3D hit;
96 if (!world->sphereCast(fromX, fromY, fromZ, toX, toY, toZ, radius, maskBits,
97 ignoredBodyId, &hit))
98 continue;
99 if (!out->hit || hit.fraction < out->fraction) {
100 out->hit = true;
101 out->bodyId = hit.bodyId;
102 out->fraction = hit.fraction;
103 out->x = hit.x;
104 out->y = hit.y;
105 out->z = hit.z;
106 out->normalX = hit.nx;
107 out->normalY = hit.ny;
108 out->normalZ = hit.nz;
109 }
110 }
111 return out->hit;
112 }
113
114private:
115 struct RegisteredWorld {
116 World3D* world = nullptr;
117 std::weak_ptr<const void> lifetime;
118 };
119
120 std::vector<RegisteredWorld> worlds_;
121};
122
123CameraObstructionQueryImpl& cameraObstructionQuery();
124
125class ProcgenWorldQueryImpl final : public eve::IProcgenWorldQuery {
126public:
127 eve::Result<eve::ProcgenSurfaceHit> projectDown(float x, float z, float maxY, float minY,
128 std::uint64_t maskBits) override {
131 const bool found = cameraObstructionQuery().sphereCast(
132 x, maxY, z, x, minY, z, 0.f, maskBits, -1, &hit);
134 output.hit = true;
135 output.objectId = hit.bodyId;
136 output.x = hit.x;
137 output.y = hit.y;
138 output.z = hit.z;
139 output.normalX = hit.normalX;
140 output.normalY = hit.normalY;
141 output.normalZ = hit.normalZ;
143 }
144};
145
146CameraObstructionQueryImpl& cameraObstructionQuery() {
147 static CameraObstructionQueryImpl impl;
148 return impl;
149}
150
151TargetingLineOfSightAdapter& targetingLineOfSightAdapter() {
152 static TargetingLineOfSightAdapter impl;
153 return impl;
154}
155
156} // namespace
157
159 static PhysicsQueryImpl impl;
160 static ProcgenWorldQueryImpl procgenWorldQuery;
161 eve::cap::provide<eve::IPhysicsQuery>(&impl);
162 eve::cap::provide<eve::IProcgenWorldQuery>(&procgenWorldQuery);
163 eve::cap::provide<eve::ICameraObstructionQuery>(&cameraObstructionQuery());
164 // Claim World3D through the sensing router rather than owning the single-slot
165 // `ILineOfSightQuery` capability: a grid board can then claim its own space without the two
166 // providers replacing each other by load order. `ensureLineOfSightRouter` reports Conflict
167 // when some other provider already holds the capability; that registration is left alone on
168 // purpose, so this adapter simply does not take part and the project keeps its own provider.
170 if (router)
171 router.value()
172 ->addProvider(eve::sensing::CoordinateSpace::World3D, &targetingLineOfSightAdapter())
173 .ignore("physics line-of-sight space claim was refused");
175}
176
178 if (world) cameraObstructionQuery().add(world, world->queryLifetime_);
179}
181 return targetingLineOfSightAdapter().addWorld(world);
182}
183
184} // namespace eve::physics
float w
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
float z
Definition AnimClip.cpp:738
std::string output
void * impl
glm::vec3 n
Definition Grass.cpp:63
One registered line-of-sight provider that dispatches to backends by coordinate space.
World3D * world
std::weak_ptr< const void > lifetime
float radius
std::string id
Definition PlayHost.cpp:108
bool hit
bool found
Physics-to-sensing line-of-sight capability adapter.
Cross-module query used by camera without linking against physics.
2D physics world query surface (provided by the physics module).
Optional synchronous world-query capability for procedural generation.
Move-only operation result carrying either a value or Status.
Definition Result.h:155
static Result success(T value)
Construct a successful result owning value.
Definition Result.h:164
Box3D rigid-body world. Script coordinates are meters (Box3D native), unlike 2D World which uses pixe...
Definition World3D.h:63
Optional physics backend for vehicle mobility and body attach.
Definition Climbing.h:36
eve::Result< void > registerTargetingLineOfSightWorld(World3D *world)
Registers a borrowed live World3D with the targeting LOS adapter.
void registerPhysicsArtifactProvider()
Register the physics provider in the common capability registry.
void registerPhysicsCapabilities()
Registers physics capabilities.
void registerCameraObstructionWorld(World3D *world)
Registers camera obstruction world.
Result< LineOfSightRouter * > ensureLineOfSightRouter()
The process-wide router, registered as the ILineOfSightQuery capability.
Physics-owned CPU collider provider for generated artifacts.
Closest hit returned by the optional camera-obstruction provider.
Value result for a procedural world-surface projection query.