Vulkan Schnee 0.0.1
High-performance rendering engine
Loading...
Searching...
No Matches
BoundingSphere.cpp
Go to the documentation of this file.
2
3#include <stdexcept>
4#include <glm/gtx/norm.hpp>
5
7
8namespace Math {
9 void BoundingSphere::calculate(Ecs::BoundingSphere& sphere, const std::vector<glm::vec3>& pointsToFit) {
10 if (pointsToFit.empty()) {
11 sphere.center = glm::vec3(0.0f);
12 sphere.radius = 0.0f;
13 return;
14 }
15
16 TRACY_ZONE_SCOPED_NAMED("Calculate Bounds");
17
18 // Find most separated points along each axis
19 glm::vec3 minX, maxX, minY, maxY, minZ, maxZ;
20 minX = maxX = minY = maxY = minZ = maxZ = pointsToFit[0];
21
22 for (const auto& point : pointsToFit) {
23 if (point.x < minX.x) minX = point;
24 if (point.x > maxX.x) maxX = point;
25 if (point.y < minY.y) minY = point;
26 if (point.y > maxY.y) maxY = point;
27 if (point.z < minZ.z) minZ = point;
28 if (point.z > maxZ.z) maxZ = point;
29 }
30
31 float distX = glm::distance2(minX, maxX);
32 float distY = glm::distance2(minY, maxY);
33 float distZ = glm::distance2(minZ, maxZ);
34
35 glm::vec3 p1, p2;
36 if (distX > distY && distX > distZ) {
37 p1 = minX;
38 p2 = maxX;
39 } else if (distY > distZ) {
40 p1 = minY;
41 p2 = maxY;
42 } else {
43 p1 = minZ;
44 p2 = maxZ;
45 }
46
47 // Initial sphere
48 glm::vec3 center = (p1 + p2) * 0.5f;
49 float radius = glm::distance(center, p2);
50
51 // Expand to include all points using Ritter's algorithm
52 {
53 TRACY_ZONE_SCOPED_NAMED("Expand bounds to include all points");
54
55 // First pass: find the point farthest from current center
56 float maxDistSq = 0.0f;
57 glm::vec3 farthestPoint = center;
58
59 for (const auto& point : pointsToFit) {
60 glm::vec3 diff = point - center;
61 float distSq = glm::dot(diff, diff);
62
63 if (distSq > maxDistSq) {
64 maxDistSq = distSq;
65 farthestPoint = point;
66 }
67 }
68
69 // If we found a point outside the sphere, expand the sphere
70 if (maxDistSq > radius * radius) {
71 float dist = glm::sqrt(maxDistSq);
72 float newRadius = (radius + dist) * 0.5f;
73 center += (farthestPoint - center) * ((dist - radius) / dist);
74 radius = newRadius;
75
76 // Second pass: expand again to ensure all points are included
77 maxDistSq = 0.0f;
78 for (const auto& point : pointsToFit) {
79 glm::vec3 diff = point - center;
80 float distSq = glm::dot(diff, diff);
81
82 if (distSq > maxDistSq) {
83 maxDistSq = distSq;
84 farthestPoint = point;
85 }
86 }
87
88 if (maxDistSq > radius * radius) {
89 float dist = glm::sqrt(maxDistSq);
90 float newRadius = (radius + dist) * 0.5f;
91 center += (farthestPoint - center) * ((dist - radius) / dist);
92 radius = newRadius;
93 }
94 }
95 }
96
97 sphere.center = center;
98 sphere.radius = radius;
99 }
100}
#define TRACY_ZONE_SCOPED_NAMED(name)
static void calculate(Ecs::BoundingSphere &sphere, const std::vector< glm::vec3 > &pointsToFit)
Calculates a bounding sphere for a list of points and fills the provided component.
Stores mathematical operations like calculating bounding spheres over a list of points.
A bounding sphere for an entity. Used for frustum culling.
Definition EcsData.h:193
glm::vec3 center
Definition EcsData.h:194