math.plane.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. import { Vector3, Matrix } from "./math.vector.js";
  2. /**
  3. * Represents a plane by the equation ax + by + cz + d = 0
  4. */
  5. export class Plane {
  6. /**
  7. * Creates a Plane object according to the given floats a, b, c, d and the plane equation : ax + by + cz + d = 0
  8. * @param a a component of the plane
  9. * @param b b component of the plane
  10. * @param c c component of the plane
  11. * @param d d component of the plane
  12. */
  13. constructor(a, b, c, d) {
  14. this.normal = new Vector3(a, b, c);
  15. this.d = d;
  16. }
  17. /**
  18. * @returns the plane coordinates as a new array of 4 elements [a, b, c, d].
  19. */
  20. asArray() {
  21. return [this.normal.x, this.normal.y, this.normal.z, this.d];
  22. }
  23. // Methods
  24. /**
  25. * @returns a new plane copied from the current Plane.
  26. */
  27. clone() {
  28. return new Plane(this.normal.x, this.normal.y, this.normal.z, this.d);
  29. }
  30. /**
  31. * @returns the string "Plane".
  32. */
  33. getClassName() {
  34. return "Plane";
  35. }
  36. /**
  37. * @returns the Plane hash code.
  38. */
  39. getHashCode() {
  40. let hash = this.normal.getHashCode();
  41. hash = (hash * 397) ^ (this.d | 0);
  42. return hash;
  43. }
  44. /**
  45. * Normalize the current Plane in place.
  46. * @returns the updated Plane.
  47. */
  48. normalize() {
  49. const norm = Math.sqrt(this.normal.x * this.normal.x + this.normal.y * this.normal.y + this.normal.z * this.normal.z);
  50. let magnitude = 0.0;
  51. if (norm !== 0) {
  52. magnitude = 1.0 / norm;
  53. }
  54. this.normal.x *= magnitude;
  55. this.normal.y *= magnitude;
  56. this.normal.z *= magnitude;
  57. this.d *= magnitude;
  58. return this;
  59. }
  60. /**
  61. * Applies a transformation the plane and returns the result
  62. * @param transformation the transformation matrix to be applied to the plane
  63. * @returns a new Plane as the result of the transformation of the current Plane by the given matrix.
  64. */
  65. transform(transformation) {
  66. const invertedMatrix = Plane._TmpMatrix;
  67. transformation.invertToRef(invertedMatrix);
  68. const m = invertedMatrix.m;
  69. const x = this.normal.x;
  70. const y = this.normal.y;
  71. const z = this.normal.z;
  72. const d = this.d;
  73. const normalX = x * m[0] + y * m[1] + z * m[2] + d * m[3];
  74. const normalY = x * m[4] + y * m[5] + z * m[6] + d * m[7];
  75. const normalZ = x * m[8] + y * m[9] + z * m[10] + d * m[11];
  76. const finalD = x * m[12] + y * m[13] + z * m[14] + d * m[15];
  77. return new Plane(normalX, normalY, normalZ, finalD);
  78. }
  79. /**
  80. * Compute the dot product between the point and the plane normal
  81. * @param point point to calculate the dot product with
  82. * @returns the dot product (float) of the point coordinates and the plane normal.
  83. */
  84. dotCoordinate(point) {
  85. return this.normal.x * point.x + this.normal.y * point.y + this.normal.z * point.z + this.d;
  86. }
  87. /**
  88. * Updates the current Plane from the plane defined by the three given points.
  89. * @param point1 one of the points used to construct the plane
  90. * @param point2 one of the points used to construct the plane
  91. * @param point3 one of the points used to construct the plane
  92. * @returns the updated Plane.
  93. */
  94. copyFromPoints(point1, point2, point3) {
  95. const x1 = point2.x - point1.x;
  96. const y1 = point2.y - point1.y;
  97. const z1 = point2.z - point1.z;
  98. const x2 = point3.x - point1.x;
  99. const y2 = point3.y - point1.y;
  100. const z2 = point3.z - point1.z;
  101. const yz = y1 * z2 - z1 * y2;
  102. const xz = z1 * x2 - x1 * z2;
  103. const xy = x1 * y2 - y1 * x2;
  104. const pyth = Math.sqrt(yz * yz + xz * xz + xy * xy);
  105. let invPyth;
  106. if (pyth !== 0) {
  107. invPyth = 1.0 / pyth;
  108. }
  109. else {
  110. invPyth = 0.0;
  111. }
  112. this.normal.x = yz * invPyth;
  113. this.normal.y = xz * invPyth;
  114. this.normal.z = xy * invPyth;
  115. this.d = -(this.normal.x * point1.x + this.normal.y * point1.y + this.normal.z * point1.z);
  116. return this;
  117. }
  118. /**
  119. * Checks if the plane is facing a given direction (meaning if the plane's normal is pointing in the opposite direction of the given vector).
  120. * Note that for this function to work as expected you should make sure that:
  121. * - direction and the plane normal are normalized
  122. * - epsilon is a number just bigger than -1, something like -0.99 for eg
  123. * @param direction the direction to check if the plane is facing
  124. * @param epsilon value the dot product is compared against (returns true if dot <= epsilon)
  125. * @returns True if the plane is facing the given direction
  126. */
  127. isFrontFacingTo(direction, epsilon) {
  128. const dot = Vector3.Dot(this.normal, direction);
  129. return dot <= epsilon;
  130. }
  131. /**
  132. * Calculates the distance to a point
  133. * @param point point to calculate distance to
  134. * @returns the signed distance (float) from the given point to the Plane.
  135. */
  136. signedDistanceTo(point) {
  137. return Vector3.Dot(point, this.normal) + this.d;
  138. }
  139. // Statics
  140. /**
  141. * Creates a plane from an array
  142. * @param array the array to create a plane from
  143. * @returns a new Plane from the given array.
  144. */
  145. static FromArray(array) {
  146. return new Plane(array[0], array[1], array[2], array[3]);
  147. }
  148. /**
  149. * Creates a plane from three points
  150. * @param point1 point used to create the plane
  151. * @param point2 point used to create the plane
  152. * @param point3 point used to create the plane
  153. * @returns a new Plane defined by the three given points.
  154. */
  155. static FromPoints(point1, point2, point3) {
  156. const result = new Plane(0.0, 0.0, 0.0, 0.0);
  157. result.copyFromPoints(point1, point2, point3);
  158. return result;
  159. }
  160. /**
  161. * Creates a plane from an origin point and a normal
  162. * @param origin origin of the plane to be constructed
  163. * @param normal normal of the plane to be constructed
  164. * @returns a new Plane the normal vector to this plane at the given origin point.
  165. */
  166. static FromPositionAndNormal(origin, normal) {
  167. const plane = new Plane(0.0, 0.0, 0.0, 0.0);
  168. return this.FromPositionAndNormalToRef(origin, normal, plane);
  169. }
  170. /**
  171. * Updates the given Plane "result" from an origin point and a normal.
  172. * @param origin origin of the plane to be constructed
  173. * @param normal the normalized normals of the plane to be constructed
  174. * @param result defines the Plane where to store the result
  175. * @returns result input
  176. */
  177. static FromPositionAndNormalToRef(origin, normal, result) {
  178. result.normal.copyFrom(normal);
  179. result.normal.normalize();
  180. result.d = -origin.dot(result.normal);
  181. return result;
  182. }
  183. /**
  184. * Calculates the distance from a plane and a point
  185. * @param origin origin of the plane to be constructed
  186. * @param normal normal of the plane to be constructed
  187. * @param point point to calculate distance to
  188. * @returns the signed distance between the plane defined by the normal vector at the "origin"" point and the given other point.
  189. */
  190. static SignedDistanceToPlaneFromPositionAndNormal(origin, normal, point) {
  191. const d = -(normal.x * origin.x + normal.y * origin.y + normal.z * origin.z);
  192. return Vector3.Dot(point, normal) + d;
  193. }
  194. }
  195. Plane._TmpMatrix = Matrix.Identity();
  196. //# sourceMappingURL=math.plane.js.map