Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

222 lines
4.5 KiB

  1. //--------------------------------------------------------------------------------------------------
  2. // qhHalfEdge.cpp
  3. //
  4. // Copyright(C) 2011 by D. Gregorius. All rights reserved.
  5. //--------------------------------------------------------------------------------------------------
  6. #include "qhHalfEdge.h"
  7. //--------------------------------------------------------------------------------------------------
  8. // Utilities
  9. //--------------------------------------------------------------------------------------------------
  10. bool qhHalfEdge::IsConvex( qhReal Tolerance ) const
  11. {
  12. return Face->Plane.Distance( Twin->Face->Centroid ) < -Tolerance;
  13. }
  14. //--------------------------------------------------------------------------------------------------
  15. void qhLinkFace( qhFace* Face, int Index, qhHalfEdge* Twin )
  16. {
  17. qhHalfEdge* Edge = Face->Edge;
  18. while ( Index-- > 0 )
  19. {
  20. Edge = Edge->Next;
  21. }
  22. QH_ASSERT( Edge != Twin );
  23. Edge->Twin = Twin;
  24. Twin->Twin = Edge;
  25. }
  26. //--------------------------------------------------------------------------------------------------
  27. void qhLinkFaces( qhFace* Face1, int Index1, qhFace* Face2, int Index2 )
  28. {
  29. qhHalfEdge* Edge1 = Face1->Edge;
  30. while ( Index1-- > 0 )
  31. {
  32. Edge1 = Edge1->Next;
  33. }
  34. qhHalfEdge* Edge2 = Face2->Edge;
  35. while ( Index2-- > 0 )
  36. {
  37. Edge2 = Edge2->Next;
  38. }
  39. QH_ASSERT( Edge1 != Edge2 );
  40. Edge1->Twin = Edge2;
  41. Edge2->Twin = Edge1;
  42. }
  43. //--------------------------------------------------------------------------------------------------
  44. void qhNewellPlane( qhFace* Face )
  45. {
  46. int Count = 0;
  47. qhVector3 Centroid = QH_VEC3_ZERO;
  48. qhVector3 Normal = QH_VEC3_ZERO;
  49. qhHalfEdge* Edge = Face->Edge;
  50. QH_ASSERT( Edge->Face == Face );
  51. do
  52. {
  53. qhHalfEdge* Twin = Edge->Twin;
  54. QH_ASSERT( Twin->Twin == Edge );
  55. const qhVector3& V1 = Edge->Origin->Position;
  56. const qhVector3& V2 = Twin->Origin->Position;
  57. Count++;
  58. Centroid += V1;
  59. // This seems to be more robust than N += Cross( V1, V2 )
  60. Normal.X += ( V1.Y - V2.Y ) * ( V1.Z + V2.Z );
  61. Normal.Y += ( V1.Z - V2.Z ) * ( V1.X + V2.X );
  62. Normal.Z += ( V1.X - V2.X ) * ( V1.Y + V2.Y );
  63. Edge = Edge->Next;
  64. }
  65. while ( Edge != Face->Edge );
  66. QH_ASSERT( Count > 2 );
  67. Centroid /= qhReal( Count );
  68. Face->Centroid = Centroid;
  69. qhReal Area = qhLength( Normal );
  70. QH_ASSERT( Area > qhReal( 0.0 ) );
  71. Normal /= Area;
  72. Face->Plane = qhPlane( Normal, Centroid );
  73. Face->Area = Area;
  74. }
  75. //--------------------------------------------------------------------------------------------------
  76. bool qhIsConvex( const qhFace* Face, qhReal Tolerance )
  77. {
  78. const qhHalfEdge* Edge = Face->Edge;
  79. do
  80. {
  81. qhVector3 Tail = Edge->Origin->Position;
  82. qhVector3 Head = Edge->Twin->Origin->Position;
  83. qhVector3 Offset = Head - Tail;
  84. qhVector3 Normal = qhCross( Offset, Face->Plane.Normal );
  85. qhPlane Plane( Normal, Head );
  86. Plane.Normalize();
  87. qhReal Distance = Plane.Distance( Edge->Next->Twin->Origin->Position );
  88. if ( Distance > -Tolerance )
  89. {
  90. return false;
  91. }
  92. Edge = Edge->Next;
  93. }
  94. while ( Edge != Face->Edge );
  95. return true;
  96. }
  97. //--------------------------------------------------------------------------------------------------
  98. int qhVertexCount( const qhFace* Face )
  99. {
  100. int VertexCount = 0;
  101. const qhHalfEdge* Edge = Face->Edge;
  102. do
  103. {
  104. VertexCount++;
  105. Edge = Edge->Next;
  106. }
  107. while ( Edge != Face->Edge );
  108. return VertexCount;
  109. }
  110. //--------------------------------------------------------------------------------------------------
  111. bool qhCheckConsistency( const qhFace* Face )
  112. {
  113. if ( Face->Mark == QH_MARK_DELETE )
  114. {
  115. // Face is not on the hull
  116. return false;
  117. }
  118. if ( qhVertexCount( Face ) < 3 )
  119. {
  120. // Invalid geometry
  121. return false;
  122. }
  123. const qhHalfEdge* Edge = Face->Edge;
  124. do
  125. {
  126. const qhHalfEdge* Twin = Edge->Twin;
  127. if ( Twin == NULL )
  128. {
  129. // Unreflected edge
  130. return false;
  131. }
  132. if ( Twin->Face == NULL )
  133. {
  134. // Missing face
  135. return false;
  136. }
  137. if ( Twin->Face == Face )
  138. {
  139. // Edge is connecting the same face
  140. return false;
  141. }
  142. if ( Twin->Face->Mark == QH_MARK_DELETE )
  143. {
  144. // Face is not on hull
  145. return false;
  146. }
  147. if ( Twin->Twin != Edge )
  148. {
  149. // Edge reflected incorrectly
  150. return false;
  151. }
  152. if ( Edge->Origin != Twin->Next->Origin )
  153. {
  154. // Topology error
  155. return false;
  156. }
  157. if ( Twin->Origin != Edge->Next->Origin )
  158. {
  159. // Topology error
  160. return false;
  161. }
  162. if ( Edge->Face != Face )
  163. {
  164. // Topology error
  165. return false;
  166. }
  167. Edge = Edge->Next;
  168. }
  169. while ( Edge != Face->Edge );
  170. return true;
  171. }