载入中...
搜索中...
未找到
GtsTerrainColliderRuntime.cpp
浏览该文件的文档.
2
3#include "common/Exception.h"
4#include "physics/Body3D.h"
5#include "physics/World3D.h"
7
8#include <cmath>
9#include <limits>
10#include <vector>
11
13namespace {
14struct ColliderLink {
17};
18physics::Body3D* resolve(const ColliderLink& link) {
19 auto* world = physics::World3D::findWorld(link.world);
20 return world ? world->findBody(link.body) : nullptr;
21}
22int destroy(std::vector<ColliderLink>& links) {
23 int count = 0;
24 for (const auto& link : links)
25 if (auto* world = physics::World3D::findWorld(link.world))
26 if (auto* body = world->findBody(link.body)) {
27 world->destroyBody(body);
28 ++count;
29 }
30 links.clear();
31 return count;
32}
33} // namespace
35 std::vector<ColliderLink> tiles;
36 std::uint64_t revision = 0;
37};
41 int level, float ox, float oy, float oz) {
42 if (!world.isValid() || level < 0 || level >= lods.getLevelCount() || !std::isfinite(ox) || !std::isfinite(oy) ||
43 !std::isfinite(oz))
45 "GTS collider world, level or origin is invalid",
46 "procgen.physics.gtsTerrainCollider"));
47 std::vector<ColliderLink> candidate(static_cast<std::size_t>(lods.getTileCount()));
48 try {
49 for (int tileIndex = 0; tileIndex < lods.getTileCount(); ++tileIndex) {
50 const auto* tile = lods.tileAt(tileIndex);
51 if (!tile || level >= static_cast<int>(tile->levels.size())) {
52 destroy(candidate);
54 "GTS collider tile level is missing",
55 "procgen.physics.gtsTerrainCollider"));
56 }
57 const auto& mesh = tile->levels[static_cast<std::size_t>(level)];
58 if (mesh.empty()) continue;
59 auto* body = world.newBody("static", ox + tile->offsetX, oy, oz + tile->offsetZ);
60 if (!body) {
61 destroy(candidate);
63 "GTS collider body creation failed",
64 "procgen.physics.gtsTerrainCollider"));
65 }
66 ColliderLink link{world.runtimeHandle(), body->runtimeHandle()};
67 candidate[static_cast<std::size_t>(tileIndex)] = link;
68 std::vector<std::int32_t> indices;
69 indices.reserve(mesh.indices().size());
70 for (auto index : mesh.indices()) {
71 if (index > static_cast<std::uint32_t>(std::numeric_limits<std::int32_t>::max()))
72 throw eve::Exception("mesh index exceeds physics range");
73 indices.push_back(static_cast<std::int32_t>(index));
74 }
75 try {
76 if (!body->newTriangleMeshShape(mesh.positions(), indices))
77 throw eve::Exception("shape creation returned null");
78 } catch (...) {
79 world.destroyBody(body);
80 candidate[static_cast<std::size_t>(tileIndex)] = {};
81 throw;
82 }
83 }
84 } catch (const std::exception& error) {
85 destroy(candidate);
87 Diagnostic::error(DiagnosticCode::Failed, error.what(), "procgen.physics.gtsTerrainCollider"));
88 }
89 destroy(impl_->tiles);
90 impl_->tiles = std::move(candidate);
91 ++impl_->revision;
92 if (!impl_->revision) ++impl_->revision;
93 return Result<std::uint64_t>::success(impl_->revision);
94}
96 int count = destroy(impl_->tiles);
97 ++impl_->revision;
98 if (!impl_->revision) ++impl_->revision;
100}
102 return index >= 0 && index < static_cast<int>(impl_->tiles.size())
103 ? resolve(impl_->tiles[static_cast<std::size_t>(index)])
104 : nullptr;
105}
106int GtsTerrainColliderRuntime::getTileCount() const { return static_cast<int>(impl_->tiles.size()); }
107std::uint64_t GtsTerrainColliderRuntime::getRevision() const { return impl_->revision; }
108} // namespace eve::procgen_physics
std::vector< std::uint32_t > indices
void(* destroy)(void *)
int level
std::string error
Definition Package.cpp:60
World3D * world
Mesh * mesh
std::uint32_t count
std::string body
uint32_t index
double oy
double ox
static Diagnostic error(DiagnosticCode code, std::string message, std::string path={}, DiagnosticDetails details={}, std::string source={})
Construct an error diagnostic with the standard error severity.
Definition Diagnostic.h:125
EVENGINE_API_FOUNDATION public API.
Definition Exception.h:13
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
static Result failure(Status status)
Construct a failed result from a structured status.
Definition Result.h:175
3D rigid body (Box3D) in meter-space coordinates (+Y up by convention). Owned by a World3D; create pr...
Definition Body3D.h:24
Box3D rigid-body world. Script coordinates are meters (Box3D native), unlike 2D World which uses pixe...
Definition World3D.h:63
static World3D * findWorld(PhysicsWorldHandle handle) noexcept
Resolve a live process-local world handle, or null after teardown. @thread Owning physics thread only...
Definition World3D.cpp:484
Owned result of the GTS split-and-sequential-simplify pipeline.
int getTileCount() const
Return the number of tiles, including empty source cells.
const GtsTerrainLodTile * tileAt(int index) const
Return one tile or nullptr for an invalid index. @ownership The LOD set retains ownership; the caller...
int getLevelCount() const
Return the common number of LOD levels per tile.
Result< std::uint64_t > replace(const procgen::GtsTerrainLodSet &lods, physics::World3D &world, int collisionLevel, float originX=0.f, float originY=0.f, float originZ=0.f)
Replace all colliders from one selected LOD after every candidate has succeeded.
int getTileCount() const
Return row-major tile slot count including empty cells.
physics::Body3D * getBody(int tileIndex) const
Resolve a borrowed collider body, or null for empty, stale or invalid tile slots.
std::uint64_t getRevision() const
Return the latest committed revision.
Result< int > clear()
Destroy every still-live collider body and advance the revision.
eve::RuntimeHandle< PhysicsWorldHandleTag > PhysicsWorldHandle
Generation-qualified runtime identity for a physics world.
eve::RuntimeHandle< PhysicsBodyHandleTag > PhysicsBodyHandle
Generation-qualified runtime identity for a physics body.