]> git.localhorst.tv Git - blank.git/blobdiff - src/geometry/primitive.hpp
some linting
[blank.git] / src / geometry / primitive.hpp
index 7da1096b38ddd528546748d232289a7e30fefa3a..52a3617835245382b6e2014091116cc881fc3c87 100644 (file)
@@ -1,8 +1,11 @@
 #ifndef BLANK_GEOMETRY_PRIMITIVE_HPP_
 #define BLANK_GEOMETRY_PRIMITIVE_HPP_
 
+#include "../graphics/glm.hpp"
+
 #include <algorithm>
-#include <glm/glm.hpp>
+#include <iosfwd>
+#include <glm/gtx/norm.hpp>
 
 
 namespace blank {
@@ -23,16 +26,49 @@ struct AABB {
 
        /// return distance between origin and farthest vertex
        float OriginRadius() const noexcept {
-               glm::vec3 high(glm::max(abs(min), abs(max)));
-               return length(high);
+               glm::vec3 high(glm::max(glm::abs(min), glm::abs(max)));
+               return glm::length(high);
        }
 };
 
+std::ostream &operator <<(std::ostream &, const AABB &);
+
+// TODO: this should really use setters/getters for dir and inv_dir so
+//       manipulating code doesn't "forget" to call Update()
 struct Ray {
        glm::vec3 orig;
        glm::vec3 dir;
+
+       glm::vec3 inv_dir;
+
+       void Update() noexcept {
+               inv_dir = 1.0f / dir;
+       }
+
+       /// get shortest distance of this ray's line to given point
+       float Distance(const glm::vec3 &point) const noexcept {
+               // d = |(x2-x1)×(x1-x0)|/|x2-x1|
+               // where x0 is point, and x1 and x2 are points on the line
+               // for derivation, see http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html
+               // x1 = orig
+               // x2-x1 = dir, which means |x2-x1| is 1.0
+               return glm::length(glm::cross(dir, orig - point));
+       }
+       float DistanceSquared(const glm::vec3 &point) const noexcept {
+               return glm::length2(glm::cross(dir, orig - point));
+       }
 };
 
+std::ostream &operator <<(std::ostream &, const Ray &);
+
+/// axis aligned boolean ray/box intersection test
+/// if true, dist constains distance from ray's origin to intersection point
+bool Intersection(
+       const Ray &,
+       const AABB &,
+       float &dist) noexcept;
+
+/// detailed oriented ray/box intersection test
 bool Intersection(
        const Ray &,
        const AABB &,
@@ -40,6 +76,8 @@ bool Intersection(
        float *dist = nullptr,
        glm::vec3 *normal = nullptr) noexcept;
 
+/// matrices may translate and rotate, but must not scale/shear/etc
+/// (basically the first three columns must have unit length)
 bool Intersection(
        const AABB &a_box,
        const glm::mat4 &a_m,
@@ -48,7 +86,72 @@ bool Intersection(
        float &depth,
        glm::vec3 &normal) noexcept;
 
-bool CullTest(const AABB &box, const glm::mat4 &MVP) noexcept;
+
+struct Plane {
+       glm::vec3 normal;
+       float dist;
+
+       float &A() noexcept { return normal.x; }
+       float &B() noexcept { return normal.y; }
+       float &C() noexcept { return normal.z; }
+       float &D() noexcept { return dist; }
+       float A() const noexcept { return normal.x; }
+       float B() const noexcept { return normal.y; }
+       float C() const noexcept { return normal.z; }
+       float D() const noexcept { return dist; }
+
+       Plane(const glm::vec3 &n, float d)
+       : normal(n), dist(d) { }
+       explicit Plane(const glm::vec4 &abcd)
+       : normal(abcd), dist(abcd.w) { }
+
+       void Normalize() noexcept {
+               const float l = glm::length(normal);
+               normal /= l;
+               dist /= l;
+       }
+};
+
+std::ostream &operator <<(std::ostream &, const Plane &);
+
+struct Frustum {
+       Plane plane[6];
+       Plane &Left() noexcept { return plane[0]; }
+       Plane &Right() noexcept { return plane[1]; }
+       Plane &Bottom() noexcept { return plane[2]; }
+       Plane &Top() noexcept { return plane[3]; }
+       Plane &Near() noexcept { return plane[4]; }
+       Plane &Far() noexcept { return plane[5]; }
+       const Plane &Left() const noexcept { return plane[0]; }
+       const Plane &Right() const noexcept { return plane[1]; }
+       const Plane &Bottom() const noexcept { return plane[2]; }
+       const Plane &Top() const noexcept { return plane[3]; }
+       const Plane &Near() const noexcept { return plane[4]; }
+       const Plane &Far() const noexcept { return plane[5]; }
+
+       /// create frustum from transposed MVP
+       explicit Frustum(const glm::mat4 &mat)
+       : plane{
+               Plane{ mat[3] + mat[0] },
+               Plane{ mat[3] - mat[0] },
+               Plane{ mat[3] + mat[1] },
+               Plane{ mat[3] - mat[1] },
+               Plane{ mat[3] + mat[2] },
+               Plane{ mat[3] - mat[2] },
+       } { }
+
+       void Normalize() noexcept {
+               for (Plane &p : plane) {
+                       p.Normalize();
+               }
+       }
+};
+
+std::ostream &operator <<(std::ostream &, const Plane &);
+std::ostream &operator <<(std::ostream &, const Frustum &);
+
+bool CullTest(const AABB &box, const glm::mat4 &) noexcept;
+bool CullTest(const AABB &box, const Frustum &) noexcept;
 
 }