]> git.localhorst.tv Git - blank.git/blob - src/geometry/primitive.hpp
faster ray/box test for AABBs
[blank.git] / src / geometry / primitive.hpp
1 #ifndef BLANK_GEOMETRY_PRIMITIVE_HPP_
2 #define BLANK_GEOMETRY_PRIMITIVE_HPP_
3
4 #include <algorithm>
5 #include <iosfwd>
6 #include <glm/glm.hpp>
7
8
9 namespace blank {
10
11 struct AABB {
12         glm::vec3 min;
13         glm::vec3 max;
14
15         void Adjust() noexcept {
16                 if (max.x < min.x) std::swap(max.x, min.x);
17                 if (max.y < min.y) std::swap(max.y, min.y);
18                 if (max.z < min.z) std::swap(max.z, min.z);
19         }
20
21         glm::vec3 Center() const noexcept {
22                 return min + (max - min) * 0.5f;
23         }
24
25         /// return distance between origin and farthest vertex
26         float OriginRadius() const noexcept {
27                 glm::vec3 high(glm::max(abs(min), abs(max)));
28                 return length(high);
29         }
30 };
31
32 std::ostream &operator <<(std::ostream &, const AABB &);
33
34 // TODO: this should really use setters/getters for dir and inv_dir so
35 //       manipulating code doesn't "forget" to call Update()
36 struct Ray {
37         glm::vec3 orig;
38         glm::vec3 dir;
39
40         glm::vec3 inv_dir;
41
42         void Update() noexcept {
43                 inv_dir = 1.0f / dir;
44         }
45 };
46
47 std::ostream &operator <<(std::ostream &, const Ray &);
48
49 /// axis aligned boolean ray/box intersection test
50 /// if true, dist constains distance from ray's origin to intersection point
51 bool Intersection(
52         const Ray &,
53         const AABB &,
54         float &dist) noexcept;
55
56 /// detailed oriented ray/box intersection test
57 bool Intersection(
58         const Ray &,
59         const AABB &,
60         const glm::mat4 &M,
61         float *dist = nullptr,
62         glm::vec3 *normal = nullptr) noexcept;
63
64 /// matrices may translate and rotate, but must not scale/shear/etc
65 /// (basically the first three columns must have unit length)
66 bool Intersection(
67         const AABB &a_box,
68         const glm::mat4 &a_m,
69         const AABB &b_box,
70         const glm::mat4 &b_m,
71         float &depth,
72         glm::vec3 &normal) noexcept;
73
74
75 struct Plane {
76         glm::vec3 normal;
77         float dist;
78
79         float &A() noexcept { return normal.x; }
80         float &B() noexcept { return normal.y; }
81         float &C() noexcept { return normal.z; }
82         float &D() noexcept { return dist; }
83         float A() const noexcept { return normal.x; }
84         float B() const noexcept { return normal.y; }
85         float C() const noexcept { return normal.z; }
86         float D() const noexcept { return dist; }
87
88         Plane(const glm::vec3 &n, float d)
89         : normal(n), dist(d) { }
90         Plane(const glm::vec4 &abcd)
91         : normal(abcd), dist(abcd.w) { }
92
93         void Normalize() noexcept {
94                 const float l = length(normal);
95                 normal /= l;
96                 dist /= l;
97         }
98 };
99
100 std::ostream &operator <<(std::ostream &, const Plane &);
101
102 struct Frustum {
103         Plane plane[6];
104         Plane &Left() noexcept { return plane[0]; }
105         Plane &Right() noexcept { return plane[1]; }
106         Plane &Bottom() noexcept { return plane[2]; }
107         Plane &Top() noexcept { return plane[3]; }
108         Plane &Near() noexcept { return plane[4]; }
109         Plane &Far() noexcept { return plane[5]; }
110         const Plane &Left() const noexcept { return plane[0]; }
111         const Plane &Right() const noexcept { return plane[1]; }
112         const Plane &Bottom() const noexcept { return plane[2]; }
113         const Plane &Top() const noexcept { return plane[3]; }
114         const Plane &Near() const noexcept { return plane[4]; }
115         const Plane &Far() const noexcept { return plane[5]; }
116
117         /// create frustum from transposed MVP
118         Frustum(const glm::mat4 &mat)
119         : plane{
120                 { mat[3] + mat[0] },
121                 { mat[3] - mat[0] },
122                 { mat[3] + mat[1] },
123                 { mat[3] - mat[1] },
124                 { mat[3] + mat[2] },
125                 { mat[3] - mat[2] },
126         } { }
127
128         void Normalize() noexcept {
129                 for (Plane &p : plane) {
130                         p.Normalize();
131                 }
132         }
133 };
134
135 std::ostream &operator <<(std::ostream &, const Plane &);
136 std::ostream &operator <<(std::ostream &, const Frustum &);
137
138 bool CullTest(const AABB &box, const glm::mat4 &) noexcept;
139 bool CullTest(const AABB &box, const Frustum &) noexcept;
140
141 }
142
143 #endif