1 module gl3n.plane; 2 3 private { 4 import gl3n.linalg : Vector, dot, vec3; 5 import gl3n.math : almost_equal; 6 7 import std.traits : isFloatingPoint; 8 } 9 10 11 /// Base template for all plane-types. 12 /// Params: 13 /// type = all values get stored as this type (must be floating point) 14 struct PlaneT(type = float) if(isFloatingPoint!type) { 15 alias type pt; /// Holds the internal type of the plane. 16 alias Vector!(pt, 3) vec3; /// Convenience alias to the corresponding vector type. 17 18 union { 19 struct { 20 pt a; /// normal.x 21 pt b; /// normal.y 22 pt c; /// normal.z 23 } 24 25 vec3 normal; /// Holds the planes normal. 26 } 27 28 pt d; /// Holds the planes "constant" (HNF). 29 30 @safe pure nothrow: 31 32 /// Constructs the plane, from either four scalars of type $(I pt) 33 /// or from a 3-dimensional vector (= normal) and a scalar. 34 this(pt a, pt b, pt c, pt d) { 35 this.a = a; 36 this.b = b; 37 this.c = c; 38 this.d = d; 39 } 40 41 /// ditto 42 this(vec3 normal, pt d) { 43 this.normal = normal; 44 this.d = d; 45 } 46 47 unittest { 48 Plane p = Plane(0.0f, 1.0f, 2.0f, 3.0f); 49 assert(p.normal == vec3(0.0f, 1.0f, 2.0f)); 50 assert(p.d == 3.0f); 51 52 p.normal.x = 4.0f; 53 assert(p.normal == vec3(4.0f, 1.0f, 2.0f)); 54 assert(p.a == 4.0f); 55 assert(p.b == 1.0f); 56 assert(p.c == 2.0f); 57 assert(p.d == 3.0f); 58 } 59 60 /// Normalizes the plane inplace. 61 void normalize() { 62 pt det = 1.0 / normal.length; 63 normal *= det; 64 d *= det; 65 } 66 67 /// Returns a normalized copy of the plane. 68 @property PlaneT normalized() const { 69 PlaneT ret = PlaneT(a, b, c, d); 70 ret.normalize(); 71 return ret; 72 } 73 74 unittest { 75 Plane p = Plane(0.0f, 1.0f, 2.0f, 3.0f); 76 Plane pn = p.normalized(); 77 assert(pn.normal == vec3(0.0f, 1.0f, 2.0f).normalized); 78 assert(almost_equal(pn.d, 3.0f/vec3(0.0f, 1.0f, 2.0f).length)); 79 p.normalize(); 80 assert(p == pn); 81 } 82 83 /// Returns the distance from a point to the plane. 84 /// Note: the plane $(RED must) be normalized, the result can be negative. 85 pt distance(vec3 point) const { 86 return dot(point, normal) + d; 87 } 88 89 /// Returns the distance from a point to the plane. 90 /// Note: the plane does not have to be normalized, the result can be negative. 91 pt ndistance(vec3 point) const { 92 return (dot(point, normal) + d) / normal.length; 93 } 94 95 unittest { 96 Plane p = Plane(-1.0f, 4.0f, 19.0f, -10.0f); 97 assert(almost_equal(p.ndistance(vec3(5.0f, -2.0f, 0.0f)), -1.182992)); 98 assert(almost_equal(p.ndistance(vec3(5.0f, -2.0f, 0.0f)), 99 p.normalized.distance(vec3(5.0f, -2.0f, 0.0f)))); 100 } 101 102 bool opEquals(PlaneT other) const { 103 return other.normal == normal && other.d == d; 104 } 105 106 } 107 108 alias PlaneT!(float) Plane;