Triangle.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /******************************************************************************
  2. Use 'Tri2' to handle 2D triangles, Flt type
  3. Use 'Tri' to handle 3D triangles, Flt type
  4. Use 'TriD2' to handle 2D triangles, Dbl type
  5. Use 'TriD' to handle 3D triangles, Dbl type
  6. Use 'GetNormal' to calculate surface normal from 3 surface points.
  7. /******************************************************************************/
  8. // calculate normal from 3 triangle points
  9. Vec GetNormal (C Vec &p0, C Vec &p1, C Vec &p2);
  10. VecD GetNormal (C VecD &p0, C VecD &p1, C VecD &p2);
  11. Vec GetNormalU(C Vec &p0, C Vec &p1, C Vec &p2); // calculate un-normalized normal vector from 3 triangle points (length of the vector is equal to the area of the triangle * 2)
  12. VecD GetNormalU(C VecD &p0, C VecD &p1, C VecD &p2); // calculate un-normalized normal vector from 3 triangle points (length of the vector is equal to the area of the triangle * 2)
  13. #if EE_PRIVATE
  14. Vec GetNormalU ( C Vec &p1, C Vec &p2); // this is 'GetNormalU' with "p0==VecZero"
  15. Vec GetNormalEdge(C Vec &p0, C Vec &p1 ); // calculate partial normal vector from 2 edge points, this needs to be called for every edge in a polygon and summed together
  16. #endif
  17. // calculate triangle area
  18. Flt TriArea2(C Vec &p0, C Vec &p1, C Vec &p2); // calculate "area of the triangle * 2", this is the same as "GetNormalU(p0, p1, p2).length()"
  19. Dbl TriArea2(C VecD &p0, C VecD &p1, C VecD &p2); // calculate "area of the triangle * 2", this is the same as "GetNormalU(p0, p1, p2).length()"
  20. /******************************************************************************/
  21. struct Tri2 // Triangle 2D
  22. {
  23. Vec2 p[3]; // points
  24. Tri2& set (C Vec2 &p0, C Vec2 &p1, C Vec2 &p2) {p[0]=p0; p[1]=p1; p[2]=p2; return T;}
  25. Tri2& setArrow(Flt direction, Flt angle=PI2/3);
  26. // get
  27. Vec2 center ( )C {return Avg(p[0], p[1], p[2]);} // get center
  28. Edge2 edge0 ( )C {return Edge2(p[0], p[1]);} // get 0-1 edge
  29. Edge2 edge1 ( )C {return Edge2(p[1], p[2]);} // get 1-2 edge
  30. Edge2 edge2 ( )C {return Edge2(p[2], p[0]);} // get 2-0 edge
  31. Flt area ( )C; // get surface area
  32. Bool valid (Flt eps=EPS)C; // if valid (points aren't inline)
  33. Bool clockwise( )C; // if points are in clockwise order
  34. // operations
  35. void circularLerp(Tri2 *tri, Int num)C; // set 'tri' 'num' number of triangles as a circular interpolation of the current triangle, interpolation occurs between p[1] and p[2] points, p[0] stays the same as in current triangle
  36. // draw
  37. void draw(C Color &color=WHITE, Bool fill=true)C;
  38. Tri2& operator+=(C Vec2 &v);
  39. Tri2& operator-=(C Vec2 &v);
  40. Tri2& operator*=( Flt r);
  41. Tri2& operator/=( Flt r);
  42. friend Tri2 operator+ (C Tri2 &tri, C Vec2 &v) {return Tri2(tri)+=v;}
  43. friend Tri2 operator- (C Tri2 &tri, C Vec2 &v) {return Tri2(tri)-=v;}
  44. friend Tri2 operator* (C Tri2 &tri, Flt r) {return Tri2(tri)*=r;}
  45. friend Tri2 operator/ (C Tri2 &tri, Flt r) {return Tri2(tri)/=r;}
  46. Tri2() {}
  47. Tri2(C Vec2 &p0, C Vec2 &p1, C Vec2 &p2) {set(p0, p1, p2);}
  48. Tri2(C TriD2 &tri);
  49. };
  50. /******************************************************************************/
  51. struct TriD2 // Triangle 2D (double precision)
  52. {
  53. VecD2 p[3]; // points
  54. TriD2& set(C VecD2 &p0, C VecD2 &p1, C VecD2 &p2) {p[0]=p0; p[1]=p1; p[2]=p2; return T;}
  55. // get
  56. VecD2 center ()C {return Avg(p[0], p[1], p[2]);} // get center
  57. EdgeD2 edge0 ()C {return EdgeD2(p[0], p[1]);} // get 0-1 edge
  58. EdgeD2 edge1 ()C {return EdgeD2(p[1], p[2]);} // get 1-2 edge
  59. EdgeD2 edge2 ()C {return EdgeD2(p[2], p[0]);} // get 2-0 edge
  60. Dbl area ()C; // get surface area
  61. Bool clockwise()C; // if points are in clockwise order
  62. // draw
  63. void draw(C Color &color=WHITE, Bool fill=true)C;
  64. TriD2& operator+=(C VecD2 &v);
  65. TriD2& operator-=(C VecD2 &v);
  66. TriD2& operator*=( Dbl r);
  67. TriD2& operator/=( Dbl r);
  68. friend TriD2 operator+ (C TriD2 &tri, C VecD2 &v) {return TriD2(tri)+=v;}
  69. friend TriD2 operator- (C TriD2 &tri, C VecD2 &v) {return TriD2(tri)-=v;}
  70. friend TriD2 operator* (C TriD2 &tri, Dbl r) {return TriD2(tri)*=r;}
  71. friend TriD2 operator/ (C TriD2 &tri, Dbl r) {return TriD2(tri)/=r;}
  72. TriD2() {}
  73. TriD2(C VecD2 &p0, C VecD2 &p1, C VecD2 &p2) {set(p0, p1, p2);}
  74. TriD2(C Tri2 &tri);
  75. };
  76. /******************************************************************************/
  77. struct Tri // Triangle 3D
  78. {
  79. Vec p[3], // points
  80. n ; // normal
  81. Tri& set (C Vec &p0, C Vec &p1, C Vec &p2, C Vec *normal=null);
  82. Tri& setNormal() {n=getNormal(); return T;} // recalculate normal
  83. // get
  84. Vec center ( )C {return Avg (p[0], p[1], p[2] );} // get center
  85. Plane plane ( )C {return Plane(p[0], n );} // return as Plane
  86. Edge edge (Int n )C {return Edge (p[Mod(n,3)], p[Mod(n+1,3)]);} // get n-th edge
  87. Edge edge0 ( )C {return Edge (p[ 0 ], p[ 1 ]);} // get 0-1 edge
  88. Edge edge1 ( )C {return Edge (p[ 1 ], p[ 2 ]);} // get 1-2 edge
  89. Edge edge2 ( )C {return Edge (p[ 2 ], p[ 0 ]);} // get 2-0 edge
  90. Vec getNormal ( )C {return GetNormal (p[0], p[1], p[2]);} // calculate normalized normal vector from triangle points
  91. Vec getNormalU( )C {return GetNormalU(p[0], p[1], p[2]);} // calculate un-normalized normal vector from triangle points (length of the vector is proportional to the area of the triangle)
  92. Flt area ( )C; // get surface area
  93. Bool valid (Flt eps=EPS)C; // if valid (points aren't inline)
  94. Bool coplanar (C Tri &tri )C; // if coplanar
  95. // operations
  96. void circularLerp(Tri *tri, Int num)C; // set 'tri' 'num' number of triangles as a circular interpolation of the current triangle, interpolation occurs between p[1] and p[2] points, p[0] stays the same as in current triangle
  97. // draw
  98. void draw(C Color &color=WHITE, Bool fill=false)C; // this relies on active object matrix which can be set using 'SetMatrix' function
  99. Tri& operator+=(C Vec &v);
  100. Tri& operator-=(C Vec &v);
  101. Tri& operator*=( Flt r);
  102. Tri& operator/=( Flt r);
  103. friend Tri operator+ (C Tri &tri, C Vec &v) {return Tri(tri)+=v;}
  104. friend Tri operator- (C Tri &tri, C Vec &v) {return Tri(tri)-=v;}
  105. friend Tri operator* (C Tri &tri, Flt r) {return Tri(tri)*=r;}
  106. friend Tri operator/ (C Tri &tri, Flt r) {return Tri(tri)/=r;}
  107. Tri() {}
  108. Tri(C Vec &p0, C Vec &p1, C Vec &p2, C Vec *normal=null) {set(p0, p1, p2, normal);}
  109. Tri(C TriD &tri);
  110. };
  111. /******************************************************************************/
  112. struct TriD // Triangle 3D (double precision)
  113. {
  114. VecD p[3], // points
  115. n ; // normal
  116. TriD& set (C VecD &p0, C VecD &p1, C VecD &p2, C VecD *normal=null);
  117. TriD& setNormal() {n=GetNormal(p[0], p[1], p[2]); return T;} // recalculate normal
  118. // get
  119. VecD center ( )C {return Avg (p[0], p[1], p[2]);} // get center
  120. PlaneD plane ( )C {return PlaneD(p[0], n );} // return as PlaneD
  121. EdgeD edge0 ( )C {return EdgeD (p[0], p[1] );} // get 0-1 edge
  122. EdgeD edge1 ( )C {return EdgeD (p[1], p[2] );} // get 1-2 edge
  123. EdgeD edge2 ( )C {return EdgeD (p[2], p[0] );} // get 2-0 edge
  124. Dbl area ( )C; // get surface area
  125. Bool coplanar(C TriD &tri)C; // if coplanar
  126. // draw
  127. void draw(C Color &color=WHITE, Bool fill=false)C; // this relies on active object matrix which can be set using 'SetMatrix' function
  128. TriD& operator+=(C VecD &v);
  129. TriD& operator-=(C VecD &v);
  130. TriD& operator*=( Dbl r);
  131. TriD& operator/=( Dbl r);
  132. friend TriD operator+ (C TriD &tri, C VecD &v) {return TriD(tri)+=v;}
  133. friend TriD operator- (C TriD &tri, C VecD &v) {return TriD(tri)-=v;}
  134. friend TriD operator* (C TriD &tri, Dbl r) {return TriD(tri)*=r;}
  135. friend TriD operator/ (C TriD &tri, Dbl r) {return TriD(tri)/=r;}
  136. TriD() {}
  137. TriD(C VecD &p0, C VecD &p1, C VecD &p2, C VecD *normal=null) {set(p0, p1, p2, normal);}
  138. TriD(C Tri &tri);
  139. };
  140. /******************************************************************************/
  141. // angle
  142. Flt TriABAngle(Flt a_length, Flt b_length, Flt c_length); // calculate the angle between 'a' 'b' sides of a triangle made from 'a', 'b', 'c' sides when length of the sides are known
  143. // return blending factors 'blend' that (blend.x*tri.p[0] + blend.y*tri.p[1] + blend.z*tri.p[2] == p), these are also known as "barycentric coordinates"
  144. Vec TriBlend(C Vec2 &p, C Tri2 &tri);
  145. VecD TriBlend(C VecD2 &p, C TriD2 &tri);
  146. Vec TriBlend(C Vec &p, C Tri &tri, Bool pos_on_tri_plane); // 'pos_on_tri_plane'=if 'p' position lies on 'tri' triangle plane (if you're not sure, then set false)
  147. VecD TriBlend(C VecD &p, C TriD &tri, Bool pos_on_tri_plane); // 'pos_on_tri_plane'=if 'p' position lies on 'tri' triangle plane (if you're not sure, then set false)
  148. // return blending factors 'blend' that (blend.x*p0 + blend.y*p1 + blend.z*p2 + blend.w*p3 == p), these are also known as "barycentric coordinates"
  149. Vec4 TetraBlend(C Vec &p, C Vec &p0, C Vec &p1, C Vec &p2, C Vec &p3);
  150. // get volume of a Tetrahedron shape
  151. Flt TetraVolume(C Vec &a, C Vec &b, C Vec &c, C Vec &d);
  152. // distance
  153. Flt Dist(C Vec2 &point, C Tri2 &tri, DIST_TYPE *type=null); // distance between point and a triangle
  154. Flt Dist(C Vec &point, C Tri &tri, DIST_TYPE *type=null); // distance between point and a triangle
  155. Flt Dist(C Edge &edge , C Tri &tri); // distance between edge and a triangle
  156. Flt Dist(C Tri &a , C Tri &b ); // distance between triangle and a triangle
  157. // distance between point and plane (from triangle)
  158. inline Flt DistPointPlane(C Vec &point, C Tri &tri) {return DistPointPlane(point, tri.p[0], tri.n);}
  159. inline Dbl DistPointPlane(C VecD &point, C TriD &tri) {return DistPointPlane(point, tri.p[0], tri.n);}
  160. // if points cuts triangle assuming they're coplanar (epsilon=0)
  161. Bool Cuts(C Vec2 &point, C Tri2 &tri);
  162. Bool Cuts(C VecD2 &point, C TriD2 &tri);
  163. Bool Cuts(C Vec &point, C Tri &tri);
  164. Bool Cuts(C VecD &point, C TriD &tri);
  165. #if EE_PRIVATE
  166. Bool Cuts(C Vec &point, C Tri &tri, C Vec (&tri_cross)[3]);
  167. #endif
  168. // if points cuts triangle assuming they're coplanar (epsilon=EPS)
  169. Bool CutsEps(C Vec2 &point, C Tri2 &tri);
  170. Bool CutsEps(C VecD2 &point, C TriD2 &tri);
  171. Bool CutsEps(C Vec &point, C Tri &tri);
  172. Bool CutsEps(C VecD &point, C TriD &tri);
  173. // if edge cuts triangle
  174. Bool Cuts(C Edge &edge, C Tri &tri);
  175. // if triangle cuts plane, return number of contacts (-1=co-planar, 0=zero, 1=one, 2=two), and set them as edge.p[]
  176. Int CutsTriPlane (C Tri &tri, C Plane &plane, Edge &edge);
  177. Int CutsTriPlane (C TriD &tri, C PlaneD &plane, EdgeD &edge);
  178. Int CutsTriPlaneEps(C Tri &tri, C Plane &plane, Edge &edge);
  179. Int CutsTriPlaneEps(C TriD &tri, C PlaneD &plane, EdgeD &edge);
  180. // if moving point cuts static triangle (epsilon=0)
  181. Bool SweepPointTri(C Vec &point, C Vec &move, C Tri &tri, Flt *hit_frac=null, Vec *hit_pos=null, Bool two_sided=false);
  182. // if moving point cuts static triangle (epsilon=EPS)
  183. Bool SweepPointTriEps(C Vec &point, C Vec &move, C Tri &tri, Flt *hit_frac=null, Vec *hit_pos=null, Bool two_sided=false);
  184. // clip edge inside triangle
  185. Int Clip(Edge2 &edge, C Tri2 &tri);
  186. Int Clip(EdgeD2 &edge, C TriD2 &tri);
  187. /******************************************************************************/