IceTriangle.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2. /**
  3. * Contains a handy triangle class.
  4. * \file IceTriangle.cpp
  5. * \author Pierre Terdiman
  6. * \date January, 17, 2000
  7. */
  8. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  9. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  10. // Precompiled Header
  11. #include "Stdafx.h"
  12. using namespace IceMaths;
  13. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  14. /**
  15. * Contains a triangle class.
  16. *
  17. * \class Tri
  18. * \author Pierre Terdiman
  19. * \version 1.0
  20. * \date 08.15.98
  21. */
  22. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  23. static sdword VPlaneSideEps(const Point& v, const Plane& plane, float epsilon)
  24. {
  25. // Compute distance from current vertex to the plane
  26. float Dist = plane.Distance(v);
  27. // Compute side:
  28. // 1 = the vertex is on the positive side of the plane
  29. // -1 = the vertex is on the negative side of the plane
  30. // 0 = the vertex is on the plane (within epsilon)
  31. return Dist > epsilon ? 1 : Dist < -epsilon ? -1 : 0;
  32. }
  33. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  34. /**
  35. * Flips the winding order.
  36. */
  37. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  38. void Triangle::Flip()
  39. {
  40. Point Tmp = mVerts[1];
  41. mVerts[1] = mVerts[2];
  42. mVerts[2] = Tmp;
  43. }
  44. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  45. /**
  46. * Computes the triangle area.
  47. * \return the area
  48. */
  49. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  50. float Triangle::Area() const
  51. {
  52. const Point& p0 = mVerts[0];
  53. const Point& p1 = mVerts[1];
  54. const Point& p2 = mVerts[2];
  55. return ((p0 - p1)^(p0 - p2)).Magnitude() * 0.5f;
  56. }
  57. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  58. /**
  59. * Computes the triangle perimeter.
  60. * \return the perimeter
  61. */
  62. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  63. float Triangle::Perimeter() const
  64. {
  65. const Point& p0 = mVerts[0];
  66. const Point& p1 = mVerts[1];
  67. const Point& p2 = mVerts[2];
  68. return p0.Distance(p1)
  69. + p0.Distance(p2)
  70. + p1.Distance(p2);
  71. }
  72. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  73. /**
  74. * Computes the triangle compacity.
  75. * \return the compacity
  76. */
  77. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  78. float Triangle::Compacity() const
  79. {
  80. float P = Perimeter();
  81. if(P==0.0f) return 0.0f;
  82. return (4.0f*PI*Area()/(P*P));
  83. }
  84. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  85. /**
  86. * Computes the triangle normal.
  87. * \param normal [out] the computed normal
  88. */
  89. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  90. void Triangle::Normal(Point& normal) const
  91. {
  92. const Point& p0 = mVerts[0];
  93. const Point& p1 = mVerts[1];
  94. const Point& p2 = mVerts[2];
  95. normal = ((p0 - p1)^(p0 - p2)).Normalize();
  96. }
  97. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  98. /**
  99. * Computes the triangle denormalized normal.
  100. * \param normal [out] the computed normal
  101. */
  102. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  103. void Triangle::DenormalizedNormal(Point& normal) const
  104. {
  105. const Point& p0 = mVerts[0];
  106. const Point& p1 = mVerts[1];
  107. const Point& p2 = mVerts[2];
  108. normal = ((p0 - p1)^(p0 - p2));
  109. }
  110. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  111. /**
  112. * Computes the triangle center.
  113. * \param center [out] the computed center
  114. */
  115. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  116. void Triangle::Center(Point& center) const
  117. {
  118. const Point& p0 = mVerts[0];
  119. const Point& p1 = mVerts[1];
  120. const Point& p2 = mVerts[2];
  121. center = (p0 + p1 + p2)*INV3;
  122. }
  123. PartVal Triangle::TestAgainstPlane(const Plane& plane, float epsilon) const
  124. {
  125. bool Pos = false, Neg = false;
  126. // Loop through all vertices
  127. for(udword i=0;i<3;i++)
  128. {
  129. // Compute side:
  130. sdword Side = VPlaneSideEps(mVerts[i], plane, epsilon);
  131. if (Side < 0) Neg = true;
  132. else if (Side > 0) Pos = true;
  133. }
  134. if (!Pos && !Neg) return TRI_ON_PLANE;
  135. else if (Pos && Neg) return TRI_INTERSECT;
  136. else if (Pos && !Neg) return TRI_PLUS_SPACE;
  137. else if (!Pos && Neg) return TRI_MINUS_SPACE;
  138. // What?!
  139. return TRI_FORCEDWORD;
  140. }
  141. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  142. /**
  143. * Computes the triangle moment.
  144. * \param m [out] the moment
  145. */
  146. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  147. /*
  148. void Triangle::ComputeMoment(Moment& m)
  149. {
  150. // Compute the area of the triangle
  151. m.mArea = Area();
  152. // Compute the centroid
  153. Center(m.mCentroid);
  154. // Second-order components. Handle zero-area faces.
  155. Point& p = mVerts[0];
  156. Point& q = mVerts[1];
  157. Point& r = mVerts[2];
  158. if(m.mArea==0.0f)
  159. {
  160. // This triangle has zero area. The second order components would be eliminated with the usual formula, so, for the
  161. // sake of robustness we use an alternative form. These are the centroid and second-order components of the triangle's vertices.
  162. m.mCovariance.m[0][0] = (p.x*p.x + q.x*q.x + r.x*r.x);
  163. m.mCovariance.m[0][1] = (p.x*p.y + q.x*q.y + r.x*r.y);
  164. m.mCovariance.m[0][2] = (p.x*p.z + q.x*q.z + r.x*r.z);
  165. m.mCovariance.m[1][1] = (p.y*p.y + q.y*q.y + r.y*r.y);
  166. m.mCovariance.m[1][2] = (p.y*p.z + q.y*q.z + r.y*r.z);
  167. m.mCovariance.m[2][2] = (p.z*p.z + q.z*q.z + r.z*r.z);
  168. m.mCovariance.m[2][1] = m.mCovariance.m[1][2];
  169. m.mCovariance.m[1][0] = m.mCovariance.m[0][1];
  170. m.mCovariance.m[2][0] = m.mCovariance.m[0][2];
  171. }
  172. else
  173. {
  174. const float OneOverTwelve = 1.0f / 12.0f;
  175. m.mCovariance.m[0][0] = m.mArea * (9.0f * m.mCentroid.x*m.mCentroid.x + p.x*p.x + q.x*q.x + r.x*r.x) * OneOverTwelve;
  176. m.mCovariance.m[0][1] = m.mArea * (9.0f * m.mCentroid.x*m.mCentroid.y + p.x*p.y + q.x*q.y + r.x*r.y) * OneOverTwelve;
  177. m.mCovariance.m[1][1] = m.mArea * (9.0f * m.mCentroid.y*m.mCentroid.y + p.y*p.y + q.y*q.y + r.y*r.y) * OneOverTwelve;
  178. m.mCovariance.m[0][2] = m.mArea * (9.0f * m.mCentroid.x*m.mCentroid.z + p.x*p.z + q.x*q.z + r.x*r.z) * OneOverTwelve;
  179. m.mCovariance.m[1][2] = m.mArea * (9.0f * m.mCentroid.y*m.mCentroid.z + p.y*p.z + q.y*q.z + r.y*r.z) * OneOverTwelve;
  180. m.mCovariance.m[2][2] = m.mArea * (9.0f * m.mCentroid.z*m.mCentroid.z + p.z*p.z + q.z*q.z + r.z*r.z) * OneOverTwelve;
  181. m.mCovariance.m[2][1] = m.mCovariance.m[1][2];
  182. m.mCovariance.m[1][0] = m.mCovariance.m[0][1];
  183. m.mCovariance.m[2][0] = m.mCovariance.m[0][2];
  184. }
  185. }
  186. */
  187. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  188. /**
  189. * Computes the triangle's smallest edge length.
  190. * \return the smallest edge length
  191. */
  192. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  193. float Triangle::MinEdgeLength() const
  194. {
  195. float Min = MAX_FLOAT;
  196. float Length01 = mVerts[0].Distance(mVerts[1]);
  197. float Length02 = mVerts[0].Distance(mVerts[2]);
  198. float Length12 = mVerts[1].Distance(mVerts[2]);
  199. if(Length01 < Min) Min = Length01;
  200. if(Length02 < Min) Min = Length02;
  201. if(Length12 < Min) Min = Length12;
  202. return Min;
  203. }
  204. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  205. /**
  206. * Computes the triangle's largest edge length.
  207. * \return the largest edge length
  208. */
  209. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  210. float Triangle::MaxEdgeLength() const
  211. {
  212. float Max = MIN_FLOAT;
  213. float Length01 = mVerts[0].Distance(mVerts[1]);
  214. float Length02 = mVerts[0].Distance(mVerts[2]);
  215. float Length12 = mVerts[1].Distance(mVerts[2]);
  216. if(Length01 > Max) Max = Length01;
  217. if(Length02 > Max) Max = Length02;
  218. if(Length12 > Max) Max = Length12;
  219. return Max;
  220. }
  221. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  222. /**
  223. * Computes a point on the triangle according to the stabbing information.
  224. * \param u,v [in] point's barycentric coordinates
  225. * \param pt [out] point on triangle
  226. * \param nearvtx [out] index of nearest vertex
  227. */
  228. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  229. void Triangle::ComputePoint(float u, float v, Point& pt, udword* nearvtx) const
  230. {
  231. // Compute point coordinates
  232. pt = (1.0f - u - v)*mVerts[0] + u*mVerts[1] + v*mVerts[2];
  233. // Compute nearest vertex if needed
  234. if(nearvtx)
  235. {
  236. // Compute distance vector
  237. Point d(mVerts[0].SquareDistance(pt), // Distance^2 from vertex 0 to point on the face
  238. mVerts[1].SquareDistance(pt), // Distance^2 from vertex 1 to point on the face
  239. mVerts[2].SquareDistance(pt)); // Distance^2 from vertex 2 to point on the face
  240. // Get smallest distance
  241. *nearvtx = d.SmallestAxis();
  242. }
  243. }
  244. void Triangle::Inflate(float fat_coeff, bool constant_border)
  245. {
  246. // Compute triangle center
  247. Point TriangleCenter;
  248. Center(TriangleCenter);
  249. // Don't normalize?
  250. // Normalize => add a constant border, regardless of triangle size
  251. // Don't => add more to big triangles
  252. for(udword i=0;i<3;i++)
  253. {
  254. Point v = mVerts[i] - TriangleCenter;
  255. if(constant_border) v.Normalize();
  256. mVerts[i] += v * fat_coeff;
  257. }
  258. }