face3.h 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. /*************************************************************************/
  2. /* face3.h */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* http://www.godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
  9. /* */
  10. /* Permission is hereby granted, free of charge, to any person obtaining */
  11. /* a copy of this software and associated documentation files (the */
  12. /* "Software"), to deal in the Software without restriction, including */
  13. /* without limitation the rights to use, copy, modify, merge, publish, */
  14. /* distribute, sublicense, and/or sell copies of the Software, and to */
  15. /* permit persons to whom the Software is furnished to do so, subject to */
  16. /* the following conditions: */
  17. /* */
  18. /* The above copyright notice and this permission notice shall be */
  19. /* included in all copies or substantial portions of the Software. */
  20. /* */
  21. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  22. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  23. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  24. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  25. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  26. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  27. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  28. /*************************************************************************/
  29. #ifndef FACE3_H
  30. #define FACE3_H
  31. #include "vector3.h"
  32. #include "plane.h"
  33. #include "aabb.h"
  34. #include "transform.h"
  35. class Face3 {
  36. public:
  37. enum Side {
  38. SIDE_OVER,
  39. SIDE_UNDER,
  40. SIDE_SPANNING,
  41. SIDE_COPLANAR
  42. };
  43. Vector3 vertex[3];
  44. /**
  45. *
  46. * @param p_plane plane used to split the face
  47. * @param p_res array of at least 3 faces, amount used in functio return
  48. * @param p_is_point_over array of at least 3 booleans, determining which face is over the plane, amount used in functio return
  49. * @param _epsilon constant used for numerical error rounding, to add "thickness" to the plane (so coplanar points can happen)
  50. * @return amount of faces generated by the split, either 0 (means no split possible), 2 or 3
  51. */
  52. int split_by_plane(const Plane& p_plane,Face3 *p_res,bool *p_is_point_over) const;
  53. Plane get_plane(ClockDirection p_dir=CLOCKWISE) const;
  54. Vector3 get_random_point_inside() const;
  55. Side get_side_of(const Face3& p_face,ClockDirection p_clock_dir=CLOCKWISE) const;
  56. bool is_degenerate() const;
  57. real_t get_area() const;
  58. Vector3 get_median_point() const;
  59. Vector3 get_closest_point_to(const Vector3& p_point) const;
  60. bool intersects_ray(const Vector3& p_from,const Vector3& p_dir,Vector3 * p_intersection=0) const;
  61. bool intersects_segment(const Vector3& p_from,const Vector3& p_dir,Vector3 * p_intersection=0) const;
  62. ClockDirection get_clock_dir() const; ///< todo, test if this is returning the proper clockwisity
  63. void get_support(const Vector3& p_normal,const Transform& p_transform,Vector3 *p_vertices,int* p_count,int p_max) const;
  64. void project_range(const Vector3& p_normal,const Transform& p_transform,float& r_min, float& r_max) const;
  65. AABB get_aabb() const {
  66. AABB aabb( vertex[0], Vector3() );
  67. aabb.expand_to( vertex[1] );
  68. aabb.expand_to( vertex[2] );
  69. return aabb;
  70. }
  71. bool intersects_aabb(const AABB& p_aabb) const;
  72. _FORCE_INLINE_ bool intersects_aabb2(const AABB& p_aabb) const;
  73. operator String() const;
  74. inline Face3() {}
  75. inline Face3(const Vector3 &p_v1,const Vector3 &p_v2,const Vector3 &p_v3) { vertex[0]=p_v1; vertex[1]=p_v2; vertex[2]=p_v3; }
  76. };
  77. bool Face3::intersects_aabb2(const AABB& p_aabb) const {
  78. Vector3 perp = (vertex[0]-vertex[2]).cross(vertex[0]-vertex[1]);
  79. Vector3 half_extents = p_aabb.size * 0.5;
  80. Vector3 ofs = p_aabb.pos + half_extents;
  81. Vector3 sup =Vector3(
  82. (perp.x>0) ? -half_extents.x : half_extents.x,
  83. (perp.y>0) ? -half_extents.y : half_extents.y,
  84. (perp.z>0) ? -half_extents.z : half_extents.z
  85. );
  86. float d = perp.dot(vertex[0]);
  87. float dist_a = perp.dot(ofs+sup)-d;
  88. float dist_b = perp.dot(ofs-sup)-d;
  89. if (dist_a*dist_b > 0)
  90. return false; //does not intersect the plane
  91. #define TEST_AXIS(m_ax)\
  92. {\
  93. float aabb_min=p_aabb.pos.m_ax;\
  94. float aabb_max=p_aabb.pos.m_ax+p_aabb.size.m_ax;\
  95. float tri_min,tri_max;\
  96. for (int i=0;i<3;i++) {\
  97. if (i==0 || vertex[i].m_ax > tri_max)\
  98. tri_max=vertex[i].m_ax;\
  99. if (i==0 || vertex[i].m_ax < tri_min)\
  100. tri_min=vertex[i].m_ax;\
  101. }\
  102. \
  103. if (tri_max<aabb_min || aabb_max<tri_min)\
  104. return false;\
  105. }
  106. TEST_AXIS(x);
  107. TEST_AXIS(y);
  108. TEST_AXIS(z);
  109. #undef TEST_AXIS
  110. Vector3 edge_norms[3]={
  111. vertex[0]-vertex[1],
  112. vertex[1]-vertex[2],
  113. vertex[2]-vertex[0],
  114. };
  115. for (int i=0;i<12;i++) {
  116. Vector3 from,to;
  117. switch(i) {
  118. case 0:{
  119. from=Vector3( p_aabb.pos.x+p_aabb.size.x , p_aabb.pos.y , p_aabb.pos.z );
  120. to=Vector3( p_aabb.pos.x , p_aabb.pos.y , p_aabb.pos.z );
  121. } break;
  122. case 1:{
  123. from=Vector3( p_aabb.pos.x+p_aabb.size.x , p_aabb.pos.y , p_aabb.pos.z+p_aabb.size.z );
  124. to=Vector3( p_aabb.pos.x+p_aabb.size.x , p_aabb.pos.y , p_aabb.pos.z );
  125. } break;
  126. case 2:{
  127. from=Vector3( p_aabb.pos.x , p_aabb.pos.y , p_aabb.pos.z+p_aabb.size.z );
  128. to=Vector3( p_aabb.pos.x+p_aabb.size.x , p_aabb.pos.y , p_aabb.pos.z+p_aabb.size.z );
  129. } break;
  130. case 3:{
  131. from=Vector3( p_aabb.pos.x , p_aabb.pos.y , p_aabb.pos.z );
  132. to=Vector3( p_aabb.pos.x , p_aabb.pos.y , p_aabb.pos.z+p_aabb.size.z );
  133. } break;
  134. case 4:{
  135. from=Vector3( p_aabb.pos.x , p_aabb.pos.y+p_aabb.size.y , p_aabb.pos.z );
  136. to=Vector3( p_aabb.pos.x+p_aabb.size.x , p_aabb.pos.y+p_aabb.size.y , p_aabb.pos.z );
  137. } break;
  138. case 5:{
  139. from=Vector3( p_aabb.pos.x+p_aabb.size.x , p_aabb.pos.y+p_aabb.size.y , p_aabb.pos.z );
  140. to=Vector3( p_aabb.pos.x+p_aabb.size.x , p_aabb.pos.y+p_aabb.size.y , p_aabb.pos.z+p_aabb.size.z );
  141. } break;
  142. case 6:{
  143. from=Vector3( p_aabb.pos.x+p_aabb.size.x , p_aabb.pos.y+p_aabb.size.y , p_aabb.pos.z+p_aabb.size.z );
  144. to=Vector3( p_aabb.pos.x , p_aabb.pos.y+p_aabb.size.y , p_aabb.pos.z+p_aabb.size.z );
  145. } break;
  146. case 7:{
  147. from=Vector3( p_aabb.pos.x , p_aabb.pos.y+p_aabb.size.y , p_aabb.pos.z+p_aabb.size.z );
  148. to=Vector3( p_aabb.pos.x , p_aabb.pos.y+p_aabb.size.y , p_aabb.pos.z );
  149. } break;
  150. case 8:{
  151. from=Vector3( p_aabb.pos.x , p_aabb.pos.y , p_aabb.pos.z+p_aabb.size.z );
  152. to=Vector3( p_aabb.pos.x , p_aabb.pos.y+p_aabb.size.y , p_aabb.pos.z+p_aabb.size.z );
  153. } break;
  154. case 9:{
  155. from=Vector3( p_aabb.pos.x , p_aabb.pos.y , p_aabb.pos.z );
  156. to=Vector3( p_aabb.pos.x , p_aabb.pos.y+p_aabb.size.y , p_aabb.pos.z );
  157. } break;
  158. case 10:{
  159. from=Vector3( p_aabb.pos.x+p_aabb.size.x , p_aabb.pos.y , p_aabb.pos.z );
  160. to=Vector3( p_aabb.pos.x+p_aabb.size.x , p_aabb.pos.y+p_aabb.size.y , p_aabb.pos.z );
  161. } break;
  162. case 11:{
  163. from=Vector3( p_aabb.pos.x+p_aabb.size.x , p_aabb.pos.y , p_aabb.pos.z+p_aabb.size.z );
  164. to=Vector3( p_aabb.pos.x+p_aabb.size.x , p_aabb.pos.y+p_aabb.size.y , p_aabb.pos.z+p_aabb.size.z );
  165. } break;
  166. }
  167. Vector3 e1=from-to;
  168. for (int j=0;j<3;j++) {
  169. Vector3 e2=edge_norms[j];
  170. Vector3 axis=vec3_cross( e1, e2 );
  171. if (axis.length_squared()<0.0001)
  172. continue; // coplanar
  173. //axis.normalize();
  174. Vector3 sup2 =Vector3(
  175. (axis.x>0) ? -half_extents.x : half_extents.x,
  176. (axis.y>0) ? -half_extents.y : half_extents.y,
  177. (axis.z>0) ? -half_extents.z : half_extents.z
  178. );
  179. float maxB = axis.dot(ofs+sup2);
  180. float minB = axis.dot(ofs-sup2);
  181. if (minB>maxB) {
  182. SWAP(maxB,minB);
  183. }
  184. float minT=1e20,maxT=-1e20;
  185. for (int k=0;k<3;k++) {
  186. float d=axis.dot(vertex[k]);
  187. if (d > maxT)
  188. maxT=d;
  189. if (d < minT)
  190. minT=d;
  191. }
  192. if (maxB<minT || maxT<minB)
  193. return false;
  194. }
  195. }
  196. return true;
  197. }
  198. #endif // FACE3_H