1 /** 2 Plane in hessian form. 3 4 Copyright: 5 Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. 6 Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) 7 Copyright (c) 2017-2018 Godot-D contributors 8 9 License: $(LINK2 https://opensource.org/licenses/MIT, MIT License) 10 11 12 */ 13 module godot.core.plane; 14 15 import godot.core.defs; 16 import godot.core.vector3; 17 18 import std.math; 19 20 enum ClockDirection 21 { 22 clockwise, 23 counterClockwise, 24 25 cw = clockwise, 26 ccw = counterClockwise 27 } 28 29 /** 30 Plane represents a normalized plane equation. Basically, “normal” is the normal of the plane (a,b,c normalized), and “d” is the distance from the origin to the plane (in the direction of “normal”). “Over” or “Above” the plane is considered the side of the plane towards where the normal is pointing. 31 */ 32 struct Plane 33 { 34 @nogc nothrow: 35 36 Vector3 normal = Vector3(0,0,0); 37 real_t d = 0; 38 39 Vector3 center() const 40 { 41 return normal*d; 42 } 43 44 Plane opUnary(string op : "-")() const 45 { 46 return Plane(-normal, -d); 47 } 48 49 Vector3 project(in Vector3 p_point) const 50 { 51 return p_point - normal * distanceTo(p_point); 52 } 53 54 55 void normalize() 56 { 57 real_t l = normal.length(); 58 if (l==0) 59 { 60 this=Plane(Vector3(0,0,0),0); 61 return; 62 } 63 normal/=l; 64 d/=l; 65 } 66 67 Plane normalized() const 68 { 69 Plane p = this; 70 p.normalize(); 71 return p; 72 } 73 74 Vector3 getAnyPoint() const 75 { 76 return normal*d; 77 } 78 79 Vector3 getAnyPerpendicularNormal() const 80 { 81 enum Vector3 p1 = Vector3(1,0,0); 82 enum Vector3 p2 = Vector3(0,1,0); 83 Vector3 p; 84 85 if (fabs(normal.dot(p1)) > 0.99) // if too similar to p1 86 p=p2; // use p2 87 else 88 p=p1; // use p1 89 90 p-=normal * normal.dot(p); 91 p.normalize(); 92 93 return p; 94 } 95 96 97 /* intersections */ 98 99 bool intersect3(in Plane p_plane1, in Plane p_plane2, Vector3* r_result = null) const 100 { 101 const Plane p_plane0 = this; 102 Vector3 normal0=p_plane0.normal; 103 Vector3 normal1=p_plane1.normal; 104 Vector3 normal2=p_plane2.normal; 105 106 real_t denom=normal0.cross(normal1).dot(normal2); 107 108 if (fabs(denom)<=CMP_EPSILON) 109 return false; 110 111 if (r_result) 112 { 113 *r_result = ( (normal1.cross(normal2) * p_plane0.d) + 114 (normal2.cross(normal0) * p_plane1.d) + 115 (normal0.cross(normal1) * p_plane2.d) )/denom; 116 } 117 return true; 118 } 119 120 121 bool intersectsRay(in Vector3 p_from, in Vector3 p_dir, Vector3* p_intersection = null) const 122 { 123 Vector3 segment=p_dir; 124 real_t den=normal.dot( segment ); 125 126 //printf("den is %i\n",den); 127 if (fabs(den)<=CMP_EPSILON) 128 { 129 return false; 130 } 131 132 real_t dist=(normal.dot( p_from ) - d) / den; 133 //printf("dist is %i\n",dist); 134 135 if (dist>CMP_EPSILON) 136 { //this is a ray, before the emiting pos (p_from) doesnt exist 137 return false; 138 } 139 140 dist=-dist; 141 if(p_intersection) *p_intersection = p_from + segment * dist; 142 143 return true; 144 } 145 146 bool intersectsSegment(in Vector3 p_begin, in Vector3 p_end, Vector3* p_intersection) const 147 { 148 Vector3 segment= p_begin - p_end; 149 real_t den=normal.dot( segment ); 150 151 //printf("den is %i\n",den); 152 if (fabs(den)<=CMP_EPSILON) return false; 153 154 real_t dist=(normal.dot( p_begin ) - d) / den; 155 //printf("dist is %i\n",dist); 156 157 if (dist<-CMP_EPSILON || dist > (1.0 +CMP_EPSILON)) return false; 158 159 dist=-dist; 160 if(p_intersection) *p_intersection = p_begin + segment * dist; 161 162 return true; 163 } 164 165 /* misc */ 166 167 bool isAlmostLike(in Plane p_plane) const 168 { 169 return (normal.dot( p_plane.normal ) > _PLANE_EQ_DOT_EPSILON && fabs(d-p_plane.d) < _PLANE_EQ_D_EPSILON); 170 } 171 172 173 /+String opCast(T : String)() const 174 { 175 // return normal.operator String() + ", " + rtos(d); 176 return String(); // @Todo 177 }+/ 178 179 180 181 bool isPointOver(in Vector3 p_point) const 182 { 183 return (normal.dot(p_point) > d); 184 } 185 186 real_t distanceTo(in Vector3 p_point) const 187 { 188 return (normal.dot(p_point)-d); 189 } 190 191 bool hasPoint(in Vector3 p_point,real_t _epsilon = CMP_EPSILON) const 192 { 193 real_t dist=normal.dot(p_point) - d; 194 dist=fabs(dist); 195 return ( dist <= _epsilon); 196 197 } 198 199 this(in Vector3 p_normal, real_t p_d) 200 { 201 normal=p_normal; 202 d=p_d; 203 } 204 205 this(in Vector3 p_point, in Vector3 p_normal) 206 { 207 normal=p_normal; 208 d=p_normal.dot(p_point); 209 } 210 211 this(in Vector3 p_point1, in Vector3 p_point2, in Vector3 p_point3,ClockDirection p_dir = ClockDirection.ccw) 212 { 213 if (p_dir == ClockDirection.clockwise) 214 normal=(p_point1-p_point3).cross(p_point1-p_point2); 215 else 216 normal=(p_point1-p_point2).cross(p_point1-p_point3); 217 normal.normalize(); 218 d = normal.dot(p_point1); 219 } 220 } 221