fork download
  1. #ifndef GAME_Plane3D_H
  2. #define GAME_Plane3D_H
  3.  
  4. #include "stdafx.h"
  5. #include "vertex3d.h"
  6.  
  7. // Plane3D: Шаблон класса "плоскость" в трехмерной декартовой системе координат.
  8. // Поддерживает примитивные операции над плоскостями и векторами в пространстве.
  9. // Основан на коде Алексея В. Борескова (http://s...content-available-to-author-only...d.ru)
  10. // В общем случае плоскость в трехмерном пространстве описывается уравнением:
  11. // A * x + B * y + C * z + D = 0,
  12. // где x, y и z - "плавающие" координаты любой точки на плоскости;
  13. // A, B, C - координаты нормали - вектора, перпендикулярного плоскости;
  14. // D - коэффициент "отступа" от начала координат. В случае если
  15. // нормаль имеет единичную длину -D будет тем расстоянием, которое надо
  16. // отступить от начала координат вдоль нормали, чтобы найти ближайшую
  17. // к началу координат точку на плоскости.
  18. // Коэффициенты A, B, C, D уникальны для каждой плоскости в пространстве вплоть
  19. // до общего множителя. В классе Plane3D для упрощения вычислений предполагается
  20. // что длина нормали плоскости должна быть равна 1 (т.е. A * A + B * B + C * C = 1).
  21. template < class T >
  22. class Plane3D
  23. {
  24. protected:
  25. // f1_sgn: функция, вычисляющая знак числа.
  26. // Возвращает 1, если число больше 0;
  27. // -1, если число меньше 0;
  28. // 0, если число равно 0.
  29. static int f1_sgn( const T k )
  30. {
  31. if( k > 0 ) return 1;
  32. if( k < 0 ) return -1;
  33. return 0;
  34. };
  35.  
  36. public:
  37. // EPS: статический член данных класса, содержащий предельную точность
  38. // вычислений с плавающей запятой.
  39. // По умолчанию принимается равным 1e-3f, но может быть изменен.
  40. // Методы, использующие EPS помечены в описании фразой "Использует EPS.".
  41. static T EPS;
  42.  
  43. Vertex3D< T > n; // Нормаль плоскости, т.е. вектор, перпендикулярный ей.
  44. // Координаты x, y, z этой точки соответствуют коэффициентам
  45. // A, B, C в уравнении плоскости.
  46. T dist; // Коэффициент D в уравнении плоскости.
  47.  
  48. // Конструктор по умолчанию создаёт "нулевую" плоскость.
  49. Plane3D(): n( 0, 0, 0 ), dist( 0 ) {};
  50.  
  51. // Конструктор плоскости из нормали и дистанции D.
  52. // Внимание! Параметры уже должны быть нормализованы до поступления в конструктор!
  53. Plane3D( const Vertex3D< T > &normal, T d ): n( normal ), dist( d ) {};
  54.  
  55. // Конструктор плоскости из координат нормали и дистанции D.
  56. // Внимание! Параметры уже должны быть нормализованы до поступления в конструктор!
  57. Plane3D( T nx, T ny, T nz, T d ): n( nx, ny, nz ), dist( d ) {};
  58.  
  59. // Конструктор плоскости из нормали и любой точки на плоскости.
  60. // Параметры автоматически нормализуются.
  61. Plane3D( const Vertex3D< T > &normal, const Vertex3D< T > &point ): n( normal )
  62. {
  63. n.Normalize();
  64. Vertex3D< T > temp = point;
  65. dist = -(temp & n);
  66. };
  67.  
  68. // Конструктор плоскости из трех точек, лежащих на ней, но не на одной прямой.
  69. // Параметры автоматически нормализуются.
  70. Plane3D( const Vertex3D< T > &p1, const Vertex3D< T > &p2, const Vertex3D< T > &p3 )
  71. {
  72. n = (p2 - p1) ^ (p3 - p1);
  73. n.Normalize();
  74. dist = -(p1 & n);
  75. };
  76.  
  77. // Конструктор копирования из другой плоскости.
  78. // Внимание! Параметры уже должны быть нормализованы до поступления в конструктор!
  79. Plane3D( const Plane3D< T > &plane ): n ( plane.n ), dist( plane.dist ) {};
  80.  
  81. // SignedDistanceTo: возвращает минимальное расстояние от точки v до плоскости.
  82. // Значение положительно, если точка лежит на стороне в которую направлен вектор нормали,
  83. // и отрицательно в обратном случае.
  84. T SignedDistanceTo( const Vertex3D< T > &v ) const
  85. {
  86. return (v & n) + dist;
  87. };
  88.  
  89. // DistanceTo: возвращает минимальное расстояние от точки v до плоскости.
  90. // В отличие от signedDistanceTo возвращаемое начение всегда положительно.
  91. T DistanceTo( const Vertex3D< T > &v ) const
  92. {
  93. return (T) fabs( SignedDistanceTo( v ) );
  94. };
  95.  
  96. // Point: возвращает ближайшую к началу координат точку, лежащую на плоскости.
  97. Vertex3D< T > Point() const
  98. {
  99. return (-dist) * n;
  100. }
  101.  
  102. // Classify: "классифицирует" переданную в качестве параметра точку, вовзращая:
  103. // 1, если точка лежит в полупространстве в которое направлен вектор нормали,
  104. // 0, если точка лежит в самой плоскости (с точностью до EPS!)
  105. // -1, если точка лежит в полупространстве от которой направлен вектор нормали.
  106. // Использует EPS!
  107. int Classify( const Vertex3D< T > &p ) const
  108. {
  109. int ret = 0;
  110. T v = SignedDistanceTo( p );
  111. if ( v > EPS )
  112. ret = 1;
  113. else if ( v < -EPS )
  114. ret = -1;
  115. return ret;
  116. };
  117.  
  118. // ReflectPos: "отражает" позицию точки v относительно плоскости в другое
  119. // полупространство. Другими словами смещает позицию точки вдоль перпендикуляра
  120. // опущенного из точки на плоскость на расстояние, равное удвоенному
  121. // начальному расстоянию от точки до плоскости в направлении к плоскости.
  122. void ReflectPos( Vertex3D< T > *v ) const
  123. {
  124. *v -= (2 * ((*v & n) + dist)) * n;
  125. };
  126.  
  127. // ReflectDir: "отражает" вектор направления v относительно плоскости под тем же
  128. // углом в обратную сторону (угол падения равен углу отражения).
  129. // В отличие от reflectPos отражение происходит не относительно
  130. // самой плоскости, но относительно начала координат.
  131. void ReflectDir( Vertex3D< T > *v ) const
  132. {
  133. *v -= (2 * (*v & n)) * n;
  134. };
  135.  
  136. // ReflectPlane: отражает плоскость plane относительно текущей плоскости.
  137. void ReflectPlane( Plane3D< T > *plane ) const
  138. {
  139. Vertex3D< T > p( -plane->dist * plane->n );
  140. ReflectDir( plane->n );
  141. ReflectPos( p );
  142. plane->dist = -(p & plane->n);
  143. };
  144.  
  145. // Flip: меняет местами лицевую и заднюю стороны плоскости.
  146. void Flip()
  147. {
  148. n = -n;
  149. dist = -dist;
  150. };
  151.  
  152. // ClosestPoint: сохраняет в параметр res ближайшую точку на текущей
  153. // плоскости к указанной точке p.
  154. // Возвращает минимальное расстояние от плоскости до точки p (со знаком).
  155. T ClosestPoint( const Vertex3D< T > &p, Vertex3D< T > *res ) const
  156. {
  157. T distanceToPlane3D = -dist - (p & n);
  158. *res = p + distanceToPlane3D * n;
  159. return distanceToPlane3D;
  160. };
  161.  
  162. // IntersectByRay: определяет пересекает ли луч, испущенный из точки org
  163. // в направлении dir текущую поверхность, и если да, то возвращает в
  164. // параметре t расстояние до точки пересечения.
  165. // Возвращает: true, если луч пересекает плоскость, false иначе.
  166. // В случае если возвращает true в параметр t сохраняется расстояние
  167. // до точки пересечения от точки org в единицах, равных длине вектора dir.
  168. bool IntersectByRay( const Vertex3D< T > &org, const Vertex3D< T > &dir, T *t ) const
  169. {
  170. T denom = dir & n;
  171. if ( fabs( denom ) < EPS )
  172. return false;
  173. T numer = -(dist + (org & n));
  174. *t = numer / denom;
  175. return true;
  176. };
  177.  
  178. // IntersectByRay: определяет пересекает ли луч, испущенный из точки org
  179. // в направлении dir текущую поверхность, и если да, то возвращает в
  180. // параметре res координаты точки пересечения.
  181. // Возвращает: true, если луч пересекает плоскость, false иначе.
  182. // В случае если возвращает true в параметр res сохраняются координаты пересечения.
  183. bool IntersectByRay( const Vertex3D< T > &org, const Vertex3D< T > &dir, Vertex3D< T > *res ) const
  184. {
  185. T t;
  186. if ( !IntersectByRay( org, dir, &t ) )
  187. return false;
  188. res = org + t * dir;
  189. return true;
  190. };
  191.  
  192. // SplitPolygon: рассекает полигон poly с количеством вершин polyCount
  193. // на два полигона, лежащих целиком во передней и задней полупространствах
  194. // от плоскости соответственно. Результат (точки полигонов) возвращается в
  195. // буфера точек front и back. Параметры fontCount и backCount принимают в себя
  196. // количество точек, записанных в буфер front и back соответственно.
  197. // Внимание! максимальное число выходных точек определяется исходя из геометрии
  198. // полигона и должно быть рассчитано до вызова этой функции! Результирующие
  199. // полигоны могут иметь 0, 1 или 2 точки (т.е. не являтся полигонами)!
  200. void SplitPolygon( const Vertex3D< T > *poly, int polyCount,
  201. Vertex3D< T > *front, int *frontCount,
  202. Vertex3D< T > *back, int *backCount ) const;
  203.  
  204. };
  205.  
  206. template < class T >
  207. T Plane3D< T >::EPS = 1e-3f;
  208.  
  209. /*
  210. template < class T >
  211. void SplitPolygon( const Vertex3D< T > *poly, int polyCount,
  212.   Vertex3D< T > *front, int *frontCount,
  213.   Vertex3D< T > *back, int *backCount )
  214. {
  215.   T EPS = 0.0001;
  216.   Vertex3D< T > *prevP = poly + polyCount - 1;
  217.   T prevF = SignedDistanceTo( *prevP );
  218.   *frontCount = 0;
  219.   *backCount = 0;
  220.   for ( int i = 0; i < polyCount; i++ )
  221.   {
  222.   Vertex3D< T > *curP = poly + i;
  223.   T curF = poly.SignedDistanceTo ( *curP );
  224.   if ( curF > EPS )
  225.   {
  226.   if ( prevF < -EPS )
  227.   {
  228.   T t = - curF / ( prevF - curF );
  229.   Vertex3D< T > sp = *curP + t * ( prevP - curP );
  230.   *front = sp;
  231.   fontCount++;
  232.   *back = sp;
  233.   backCount++;
  234.   }
  235.   *front = *curP;
  236.   frontCount++;
  237.   }
  238.   else
  239.   if ( curF < -EPS )
  240.   {
  241.   if ( prevF > -EPS )
  242.   {
  243.   T t = - curF / ( prevF - curF );
  244.   Vector3D< T > sp = *curP + t * ( prevP - curP );
  245.   *front = sp;
  246.   fontCount++;
  247.   *back = sp;
  248.   backCount++;
  249.   }
  250.   *back = *curP;
  251.   backCount++;
  252.   }
  253.   else
  254.   {
  255.   *front = *curP;
  256.   fontCount++;
  257.   *back = *curP;
  258.   backCount++;
  259.   }
  260.   prevP = curP;
  261.   prevF = curF;
  262.   };
  263. };
  264. */
  265.  
  266. typedef Plane3D< float > Plane3Df;
  267. typedef Plane3D< double > Plane3Dd;
  268.  
  269. #endif
Compilation error #stdin compilation error #stdout 0s 0KB
stdin
Standard input is empty
compilation info
prog.cpp:4:10: fatal error: stdafx.h: No such file or directory
 #include "stdafx.h"
          ^~~~~~~~~~
compilation terminated.
stdout
Standard output is empty