Line data Source code
1 : #pragma once
2 : #include <cstdint>
3 : #include "rbc/shapes/Sphere.hpp"
4 : #include "rbc/shapes/Box.hpp"
5 : #include "rbc/shapes/Ellipsoid.hpp"
6 : #include "rbc/shapes/Capsule.hpp"
7 : #include "rbc/shapes/Cone.hpp"
8 : #include "rbc/shapes/Plane.hpp"
9 : #include "rbc/shapes/Heightmap.hpp"
10 : #include "rbc/shapes/Mesh.hpp"
11 :
12 : namespace rbc
13 : {
14 : #define RBC_SHAPE_LIST(X, ...) \
15 : X(Sphere, sphere, ##__VA_ARGS__) \
16 : X(Box, box, ##__VA_ARGS__) \
17 : X(Ellipsoid, ellipsoid, ##__VA_ARGS__) \
18 : X(Capsule, capsule, ##__VA_ARGS__) \
19 : X(Cone, cone, ##__VA_ARGS__) \
20 : X(Plane, plane, ##__VA_ARGS__) \
21 : X(Heightmap, heightmap, ##__VA_ARGS__) \
22 : X(Mesh, mesh, ##__VA_ARGS__)
23 :
24 : #define RBC_SHAPE_LIST_INNER(X, ...) \
25 : X(Sphere, sphere, ##__VA_ARGS__) \
26 : X(Box, box, ##__VA_ARGS__) \
27 : X(Ellipsoid, ellipsoid, ##__VA_ARGS__) \
28 : X(Capsule, capsule, ##__VA_ARGS__) \
29 : X(Cone, cone, ##__VA_ARGS__) \
30 : X(Plane, plane, ##__VA_ARGS__) \
31 : X(Heightmap, heightmap, ##__VA_ARGS__) \
32 : X(Mesh, mesh, ##__VA_ARGS__)
33 :
34 : // Automatically generate the enum, struct, union, and support switch based on the master list
35 : enum struct ShapeType : uint8_t
36 : {
37 : #define GENERATE_ENUM(Type, name) Type,
38 : RBC_SHAPE_LIST(GENERATE_ENUM)
39 : #undef GENERATE_ENUM
40 : Count // Utility value to know how many shapes we have (Useful for generating the function matrix)
41 : };
42 :
43 : // Automatically generate the union of shape data
44 : struct Shape
45 : {
46 : ShapeType type;
47 :
48 : union
49 : {
50 : #define GENERATE_UNION(Type, name) Type name;
51 : RBC_SHAPE_LIST(GENERATE_UNION)
52 : #undef GENERATE_UNION
53 : };
54 :
55 96 : Shape() {} // Defualt constructor (For list initialization)
56 :
57 : // Generate constructors for each shape type for easy initialization
58 : #define GENERATE_CONSTRUCTOR(Type, name) \
59 : Shape(const Type &s) : type(ShapeType::Type), name(s) {}
60 123 : RBC_SHAPE_LIST(GENERATE_CONSTRUCTOR)
61 : #undef GENERATE_CONSTRUCTOR
62 :
63 : // Utility function so the matrix extracts the correct shape
64 : template <typename T>
65 : const T &get() const;
66 : };
67 :
68 : // Getter specializations for each shape type (Generated automatically)
69 : #define GENERATE_GETTER(Type, name) \
70 : template <> \
71 : inline const Type &Shape::get<Type>() const { return name; }
72 18812 : RBC_SHAPE_LIST(GENERATE_GETTER)
73 : #undef GENERATE_GETTER
74 :
75 : // Automatically generate the support switch
76 690 : inline m3d::vec3 shape_support(const Shape &shape, const m3d::vec3 &dir)
77 : {
78 690 : switch (shape.type)
79 : {
80 : #define GENERATE_SUPPORT(Type, name) \
81 : case ShapeType::Type: \
82 : return support(shape.name, dir);
83 690 : RBC_SHAPE_LIST(GENERATE_SUPPORT)
84 : #undef GENERATE_SUPPORT
85 0 : default:
86 0 : return m3d::vec3();
87 : }
88 : }
89 :
90 : // -------------------------------------------------------------------------
91 : // Generic AABB dispatch — lives here because this is the first place where
92 : // ALL shape types and their compute_aabb() overloads are visible.
93 : // Sphere.hpp and Box.hpp define their own overloads; we just dispatch here.
94 : // -------------------------------------------------------------------------
95 1240 : inline AABB compute_aabb(const Shape &shape, const m3d::tf &tf)
96 : {
97 1240 : switch (shape.type)
98 : {
99 : #define GEN_AABB_CASE(Type, name) \
100 : case ShapeType::Type: \
101 : return compute_aabb(shape.name, tf);
102 1240 : RBC_SHAPE_LIST(GEN_AABB_CASE)
103 : #undef GEN_AABB_CASE
104 0 : default:
105 0 : return AABB{};
106 : }
107 : }
108 :
109 : // Check that both lists have the same number of entries (Compile-time assertion)
110 : namespace test_shape_list
111 : {
112 : #define COUNT_ELEMENTS(Type, Name, ...) +1
113 :
114 : // We calculate the length of both lists separately.
115 : constexpr size_t TotalShapesOuter = 0 RBC_SHAPE_LIST(COUNT_ELEMENTS);
116 : constexpr size_t TotalShapesInner = 0 RBC_SHAPE_LIST_INNER(COUNT_ELEMENTS);
117 :
118 : static_assert(TotalShapesOuter == TotalShapesInner,
119 : "CRITICAL DESYNC: RBC_SHAPE_LIST and RBC_SHAPE_LIST_INNER must have the same entries!");
120 :
121 : // Also ensure the Enum matches the list (sanity check)
122 : static_assert(TotalShapesOuter == static_cast<size_t>(ShapeType::Count),
123 : "CRITICAL: ShapeType::Count does not match RBC_SHAPE_LIST length.");
124 : } // End of shape list sanity checks
125 : } // namespace rbc
|