Line data Source code
1 : #pragma once
2 : #include <limits>
3 : #include <math3d/math3d.hpp>
4 : #include "rbc/AABB.hpp"
5 :
6 : namespace rbc
7 : {
8 : // ── Plane (infinite half-space) ───────────────────────────────────────────
9 : // The plane surface in local space: normal · x = d
10 : // The solid half-space is normal · x >= d ("above" the plane).
11 : //
12 : // World-space plane equation (applying transform tf):
13 : // world_normal = tf.rotate_vector(normal)
14 : // world_d = d + dot(world_normal, tf.pos)
15 : //
16 : // IMPORTANT: Plane is an *infinite* shape. GJK cannot be used against it.
17 : // All CollisionAlgorithm<*, Plane> specialisations must be analytic.
18 : // They live in rbc/analytic/PlaneCollision.hpp.
19 : struct Plane
20 : {
21 : m3d::vec3 normal = {0.0, 1.0, 0.0}; // unit normal (local space)
22 : m3d::scalar d = 0.0; // offset: normal·x = d on surface
23 :
24 : Plane() = default;
25 : Plane(const m3d::vec3 &normal, m3d::scalar d) : normal(normal), d(d) {}
26 :
27 : inline bool operator==(const Plane &o) const { return normal == o.normal && d == o.d; }
28 : inline bool operator!=(const Plane &o) const { return !(*this == o); }
29 : };
30 :
31 : // ── Helpers: world-space plane parameters ────────────────────────────────
32 : inline m3d::vec3 plane_world_normal(const Plane &p, const m3d::tf &tf)
33 : {
34 : return tf.rotate_vector(p.normal);
35 : }
36 :
37 : inline m3d::scalar plane_world_d(const Plane &p, const m3d::tf &tf)
38 : {
39 : return p.d + m3d::dot(plane_world_normal(p, tf), tf.pos);
40 : }
41 :
42 : // ── Support function ──────────────────────────────────────────────────────
43 : // A half-space is unbounded in the normal direction — support returns
44 : // a very large (but finite) value so we can still call it safely.
45 : // DO NOT feed Plane to GJK; use analytic specialisations instead.
46 0 : inline m3d::vec3 support(const Plane &p, const m3d::vec3 &dir)
47 : {
48 : // If dir points into the half-space, support is "at infinity" — clamp to large value.
49 0 : constexpr m3d::scalar BIG = 1.0e15;
50 0 : if (m3d::dot(dir, p.normal) > 0.0)
51 0 : return p.normal * BIG;
52 : // Otherwise, any point on the plane surface; use origin projected onto plane.
53 0 : return p.normal * p.d;
54 : }
55 :
56 : // ── AABB: infinite in all directions ─────────────────────────────────────
57 0 : inline AABB compute_aabb(const Plane & /*p*/, const m3d::tf & /*tf*/)
58 : {
59 0 : constexpr m3d::scalar INF = std::numeric_limits<m3d::scalar>::infinity();
60 0 : return {m3d::vec3(-INF, -INF, -INF), m3d::vec3(INF, INF, INF)};
61 : }
62 : } // namespace rbc
|