1 #ifndef GONG_GEOMETRY_PRIMITIVE_HPP_
2 #define GONG_GEOMETRY_PRIMITIVE_HPP_
4 #include "../graphics/glm.hpp"
8 #include <glm/gtx/norm.hpp>
18 void Adjust() noexcept {
19 if (max.x < min.x) std::swap(max.x, min.x);
20 if (max.y < min.y) std::swap(max.y, min.y);
21 if (max.z < min.z) std::swap(max.z, min.z);
24 glm::vec3 Center() const noexcept {
25 return min + (max - min) * 0.5f;
28 /// return distance between origin and farthest vertex
29 float OriginRadius() const noexcept {
30 glm::vec3 high(glm::max(glm::abs(min), glm::abs(max)));
31 return glm::length(high);
35 std::ostream &operator <<(std::ostream &, const AABB &);
37 // TODO: this should really use setters/getters for dir and inv_dir so
38 // manipulating code doesn't "forget" to call Update()
45 void Update() noexcept {
49 /// get shortest distance of this ray's line to given point
50 float Distance(const glm::vec3 &point) const noexcept {
51 // d = |(x2-x1)×(x1-x0)|/|x2-x1|
52 // where x0 is point, and x1 and x2 are points on the line
53 // for derivation, see http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html
55 // x2-x1 = dir, which means |x2-x1| is 1.0
56 return glm::length(glm::cross(dir, orig - point));
58 float DistanceSquared(const glm::vec3 &point) const noexcept {
59 return glm::length2(glm::cross(dir, orig - point));
63 std::ostream &operator <<(std::ostream &, const Ray &);
65 /// axis aligned boolean ray/box intersection test
66 /// if true, dist constains distance from ray's origin to intersection point
70 float &dist) noexcept;
72 /// detailed oriented ray/box intersection test
77 float *dist = nullptr,
78 glm::vec3 *normal = nullptr) noexcept;
80 /// matrices may translate and rotate, but must not scale/shear/etc
81 /// (basically the first three columns must have unit length)
88 glm::vec3 &normal) noexcept;
95 float &A() noexcept { return normal.x; }
96 float &B() noexcept { return normal.y; }
97 float &C() noexcept { return normal.z; }
98 float &D() noexcept { return dist; }
99 float A() const noexcept { return normal.x; }
100 float B() const noexcept { return normal.y; }
101 float C() const noexcept { return normal.z; }
102 float D() const noexcept { return dist; }
104 Plane(const glm::vec3 &n, float d)
105 : normal(n), dist(d) { }
106 explicit Plane(const glm::vec4 &abcd)
107 : normal(abcd), dist(abcd.w) { }
109 void Normalize() noexcept {
110 const float l = glm::length(normal);
116 std::ostream &operator <<(std::ostream &, const Plane &);
120 Plane &Left() noexcept { return plane[0]; }
121 Plane &Right() noexcept { return plane[1]; }
122 Plane &Bottom() noexcept { return plane[2]; }
123 Plane &Top() noexcept { return plane[3]; }
124 Plane &Near() noexcept { return plane[4]; }
125 Plane &Far() noexcept { return plane[5]; }
126 const Plane &Left() const noexcept { return plane[0]; }
127 const Plane &Right() const noexcept { return plane[1]; }
128 const Plane &Bottom() const noexcept { return plane[2]; }
129 const Plane &Top() const noexcept { return plane[3]; }
130 const Plane &Near() const noexcept { return plane[4]; }
131 const Plane &Far() const noexcept { return plane[5]; }
133 /// create frustum from transposed MVP
134 explicit Frustum(const glm::mat4 &mat)
136 Plane{ mat[3] + mat[0] },
137 Plane{ mat[3] - mat[0] },
138 Plane{ mat[3] + mat[1] },
139 Plane{ mat[3] - mat[1] },
140 Plane{ mat[3] + mat[2] },
141 Plane{ mat[3] - mat[2] },
144 void Normalize() noexcept {
145 for (Plane &p : plane) {
151 std::ostream &operator <<(std::ostream &, const Plane &);
152 std::ostream &operator <<(std::ostream &, const Frustum &);
154 bool CullTest(const AABB &box, const glm::mat4 &) noexcept;
155 bool CullTest(const AABB &box, const Frustum &) noexcept;