Plane.h 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. #ifndef PLANE_H
  2. #define PLANE_H
  3. #include "Vector3.h"
  4. #include <cmath>
  5. typedef float real_t; // @Todo move this to a global Godot.h
  6. #define CMP_EPSILON 0.00001
  7. namespace godot {
  8. #define _PLANE_EQ_DOT_EPSILON 0.999
  9. #define _PLANE_EQ_D_EPSILON 0.0001
  10. enum ClockDirection {
  11. CLOCKWISE,
  12. COUNTERCLOCKWISE
  13. };
  14. class Plane {
  15. public:
  16. Vector3 normal;
  17. real_t d;
  18. void set_normal(const Vector3& p_normal)
  19. {
  20. this->normal = p_normal;
  21. }
  22. Vector3 get_normal() const { return normal; } ///Point is coplanar, CMP_EPSILON for precision
  23. void normalize(); // down below
  24. Plane normalized() const; // down below
  25. /* Plane-Point operations */
  26. Vector3 center() const { return normal*d; }
  27. Vector3 get_any_point() const;
  28. Vector3 get_any_perpendicular_normal() const;
  29. bool is_point_over(const Vector3 &p_point) const; ///< Point is over plane
  30. real_t distance_to(const Vector3 &p_point) const;
  31. bool has_point(const Vector3 &p_point,real_t _epsilon=CMP_EPSILON) const;
  32. /* intersections */
  33. bool intersect_3(const Plane &p_plane1, const Plane &p_plane2, Vector3 *r_result=0) const;
  34. bool intersects_ray(Vector3 p_from, Vector3 p_dir, Vector3* p_intersection) const;
  35. bool intersects_segment(Vector3 p_begin, Vector3 p_end, Vector3* p_intersection) const;
  36. Vector3 project(const Vector3& p_point) const {
  37. return p_point - normal * distance_to(p_point);
  38. }
  39. /* misc */
  40. Plane operator-() const { return Plane(-normal,-d); }
  41. bool is_almost_like(const Plane& p_plane) const;
  42. bool operator==(const Plane& p_plane) const;
  43. bool operator!=(const Plane& p_plane) const;
  44. operator String() const;
  45. Plane() { d=0; }
  46. Plane(real_t p_a, real_t p_b, real_t p_c, real_t p_d) : normal(p_a,p_b,p_c), d(p_d) { }
  47. Plane(const Vector3 &p_normal, real_t p_d);
  48. Plane(const Vector3 &p_point, const Vector3& p_normal);
  49. Plane(const Vector3 &p_point1, const Vector3 &p_point2,const Vector3 &p_point3,ClockDirection p_dir = CLOCKWISE);
  50. };
  51. void Plane::normalize() {
  52. real_t l = normal.length();
  53. if (l==0) {
  54. *this=Plane(0,0,0,0);
  55. return;
  56. }
  57. normal/=l;
  58. d/=l;
  59. }
  60. Plane Plane::normalized() const {
  61. Plane p = *this;
  62. p.normalize();
  63. return p;
  64. }
  65. Vector3 Plane::get_any_point() const {
  66. return get_normal()*d;
  67. }
  68. Vector3 Plane::get_any_perpendicular_normal() const {
  69. static const Vector3 p1 = Vector3(1,0,0);
  70. static const Vector3 p2 = Vector3(0,1,0);
  71. Vector3 p;
  72. if (::fabs(normal.dot(p1)) > 0.99) // if too similar to p1
  73. p=p2; // use p2
  74. else
  75. p=p1; // use p1
  76. p-=normal * normal.dot(p);
  77. p.normalize();
  78. return p;
  79. }
  80. /* intersections */
  81. bool Plane::intersect_3(const Plane &p_plane1, const Plane &p_plane2, Vector3 *r_result) const {
  82. const Plane &p_plane0=*this;
  83. Vector3 normal0=p_plane0.normal;
  84. Vector3 normal1=p_plane1.normal;
  85. Vector3 normal2=p_plane2.normal;
  86. real_t denom=vec3_cross(normal0,normal1).dot(normal2);
  87. if (::fabs(denom)<=CMP_EPSILON)
  88. return false;
  89. if (r_result) {
  90. *r_result = ( (vec3_cross(normal1, normal2) * p_plane0.d) +
  91. (vec3_cross(normal2, normal0) * p_plane1.d) +
  92. (vec3_cross(normal0, normal1) * p_plane2.d) )/denom;
  93. }
  94. return true;
  95. }
  96. bool Plane::intersects_ray(Vector3 p_from, Vector3 p_dir, Vector3* p_intersection) const {
  97. Vector3 segment=p_dir;
  98. real_t den=normal.dot( segment );
  99. //printf("den is %i\n",den);
  100. if (::fabs(den)<=CMP_EPSILON) {
  101. return false;
  102. }
  103. real_t dist=(normal.dot( p_from ) - d) / den;
  104. //printf("dist is %i\n",dist);
  105. if (dist>CMP_EPSILON) { //this is a ray, before the emiting pos (p_from) doesnt exist
  106. return false;
  107. }
  108. dist=-dist;
  109. *p_intersection = p_from + segment * dist;
  110. return true;
  111. }
  112. bool Plane::intersects_segment(Vector3 p_begin, Vector3 p_end, Vector3* p_intersection) const {
  113. Vector3 segment= p_begin - p_end;
  114. real_t den=normal.dot( segment );
  115. //printf("den is %i\n",den);
  116. if (::fabs(den)<=CMP_EPSILON) {
  117. return false;
  118. }
  119. real_t dist=(normal.dot( p_begin ) - d) / den;
  120. //printf("dist is %i\n",dist);
  121. if (dist<-CMP_EPSILON || dist > (1.0 +CMP_EPSILON)) {
  122. return false;
  123. }
  124. dist=-dist;
  125. *p_intersection = p_begin + segment * dist;
  126. return true;
  127. }
  128. /* misc */
  129. bool Plane::is_almost_like(const Plane& p_plane) const {
  130. return (normal.dot( p_plane.normal ) > _PLANE_EQ_DOT_EPSILON && ::fabs(d-p_plane.d) < _PLANE_EQ_D_EPSILON);
  131. }
  132. Plane::operator String() const {
  133. // return normal.operator String() + ", " + rtos(d);
  134. return String(); // @Todo
  135. }
  136. bool Plane::is_point_over(const Vector3 &p_point) const {
  137. return (normal.dot(p_point) > d);
  138. }
  139. real_t Plane::distance_to(const Vector3 &p_point) const {
  140. return (normal.dot(p_point)-d);
  141. }
  142. bool Plane::has_point(const Vector3 &p_point,real_t _epsilon) const {
  143. real_t dist=normal.dot(p_point) - d;
  144. dist=::fabs(dist);
  145. return ( dist <= _epsilon);
  146. }
  147. Plane::Plane(const Vector3 &p_normal, real_t p_d) {
  148. normal=p_normal;
  149. d=p_d;
  150. }
  151. Plane::Plane(const Vector3 &p_point, const Vector3& p_normal) {
  152. normal=p_normal;
  153. d=p_normal.dot(p_point);
  154. }
  155. Plane::Plane(const Vector3 &p_point1, const Vector3 &p_point2, const Vector3 &p_point3,ClockDirection p_dir) {
  156. if (p_dir == CLOCKWISE)
  157. normal=(p_point1-p_point3).cross(p_point1-p_point2);
  158. else
  159. normal=(p_point1-p_point2).cross(p_point1-p_point3);
  160. normal.normalize();
  161. d = normal.dot(p_point1);
  162. }
  163. bool Plane::operator==(const Plane& p_plane) const {
  164. return normal==p_plane.normal && d == p_plane.d;
  165. }
  166. bool Plane::operator!=(const Plane& p_plane) const {
  167. return normal!=p_plane.normal || d != p_plane.d;
  168. }
  169. }
  170. #endif // PLANE_H