73 if (count == 0)
return AABB();
75 float minX = std::numeric_limits<float>::max();
76 float minY = std::numeric_limits<float>::max();
77 float minZ = std::numeric_limits<float>::max();
78 float maxX = std::numeric_limits<float>::lowest();
79 float maxY = std::numeric_limits<float>::lowest();
80 float maxZ = std::numeric_limits<float>::lowest();
82 const char* ptr =
reinterpret_cast<const char*
>(positions);
83 for (
size_t i = 0; i < count; ++i) {
84 const float* pos =
reinterpret_cast<const float*
>(ptr + i * stride);
85 if (pos[0] < minX) minX = pos[0];
86 if (pos[1] < minY) minY = pos[1];
87 if (pos[2] < minZ) minZ = pos[2];
88 if (pos[0] > maxX) maxX = pos[0];
89 if (pos[1] > maxY) maxY = pos[1];
90 if (pos[2] > maxZ) maxZ = pos[2];
175 return AABB(minPt, maxPt);
185 float maxExt = extents.
GetY();
186 if (extents.
GetX() > maxExt) {
axis = 0; maxExt = extents.
GetX(); }
187 if (extents.
GetZ() > maxExt) {
axis = 2; maxExt = extents.
GetZ(); }
191 if (
axis == 0) r = std::max(extents.
GetY(), extents.
GetZ());
192 else if (
axis == 1) r = std::max(extents.
GetX(), extents.
GetZ());
193 else r = std::max(extents.
GetX(), extents.
GetY());
210 void Build(
const float* positions,
size_t count,
size_t stride,
211 const uint32_t* indexData,
size_t indexCount) {
213 const char* ptr =
reinterpret_cast<const char*
>(positions);
214 for (
size_t i = 0; i < count; ++i) {
215 const float* pos =
reinterpret_cast<const float*
>(ptr + i * stride);
218 indices.assign(indexData, indexData + indexCount);
233 using ColliderShape = std::variant<AABB, BoundingSphere, BoundingCapsule, TriangleMesh>;
239 if (
auto* aabb = std::get_if<AABB>(&shape)) {
241 }
else if (
auto* sphere = std::get_if<BoundingSphere>(&shape)) {
242 local = sphere->ToAABB();
243 }
else if (
auto* capsule = std::get_if<BoundingCapsule>(&shape)) {
244 local = capsule->ToAABB();
245 }
else if (
auto* mesh = std::get_if<TriangleMesh>(&shape)) {
246 local = mesh->bounds;
250 Vector3D scaledMin = local.
min * worldScale + worldPos;
251 Vector3D scaledMax = local.
max * worldScale + worldPos;
256 std::min(scaledMin.
GetY(), scaledMax.
GetY()),
257 std::min(scaledMin.
GetZ(), scaledMax.
GetZ())),
259 std::max(scaledMin.
GetY(), scaledMax.
GetY()),
260 std::max(scaledMin.
GetZ(), scaledMax.
GetZ()))
Collision shapes, the broadphase tree, and the world that steps them.
std::variant< AABB, BoundingSphere, BoundingCapsule, TriangleMesh > ColliderShape
Tagged union of the shapes a ColliderComponent can hold.
AABB GetWorldAABB(const ColliderShape &shape, const Vector3D &worldPos, const Vector3D &worldScale)
Transforms a local-space collider shape into a world-space AABB for broadphase queries.
Root namespace for everything the engine exposes.
Vector3D GetCenter() const
AABB Fatten(float margin) const
bool Contains(const Vector3D &point) const
AABB(const Vector3D &min, const Vector3D &max)
Vector3D GetExtents() const
AABB Merge(const AABB &other) const
float GetSurfaceArea() const
bool Overlaps(const AABB &other) const
static AABB FromVertices(const float *positions, size_t count, size_t stride)
Computes a tight AABB over raw interleaved vertex positions.
BoundingCapsule(const Vector3D ¢er, float radius, float halfHeight, int axis=1)
Vector3D GetPointA() const
World position of the capsule's positive-axis cap center.
Vector3D GetPointB() const
World position of the capsule's negative-axis cap center.
static BoundingCapsule FromAABB(const AABB &aabb)
Fits a capsule inside the AABB, picking its longest axis as the capsule axis.
static BoundingSphere FromAABB(const AABB &aabb)
Builds the sphere circumscribing the given AABB.
bool Contains(const Vector3D &point) const
bool Overlaps(const BoundingSphere &other) const
BoundingSphere(const Vector3D ¢er, float radius)
std::vector< Vector3D > vertices
void Build(const float *positions, size_t count, size_t stride, const uint32_t *indexData, size_t indexCount)
Copies vertex positions and indices out of raw mesh buffers and recomputes bounds.
std::vector< uint32_t > indices