Plane.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. /******************************************************************************/
  5. static void DrawPlane(C Color &color, Flt cell_size, Int resolution, C Vec &center, C Matrix3 &matrix, Bool ball)
  6. {
  7. Flt size=cell_size*resolution/2;
  8. Vec lf =center+size*( matrix.z-matrix.x),
  9. lb =center+size*(-matrix.z-matrix.x),
  10. rb =center+size*( matrix.x-matrix.z);
  11. VI.color(color);
  12. if(ball)
  13. {
  14. Ball ball(D.viewRange(), CamMatrix.pos/ObjMatrix);
  15. REP(resolution+1)
  16. {
  17. Flt step=i*cell_size;
  18. Vec dx =step*matrix.x,
  19. dz =step*matrix.z, a, b;
  20. if(CutsStrBall(lb+dx, matrix.z, ball, &a, &b)==2)VI.line(a, b);
  21. if(CutsStrBall(lb+dz, matrix.x, ball, &a, &b)==2)VI.line(a, b);
  22. }
  23. }else
  24. {
  25. REP(resolution+1)
  26. {
  27. Flt step=i*cell_size;
  28. Vec dx =step*matrix.x,
  29. dz =step*matrix.z;
  30. VI.line(lf+dx, lb+dx);
  31. VI.line(lb+dz, rb+dz);
  32. }
  33. }
  34. VI.end();
  35. }
  36. void Plane::drawLocal(C Color &color, Flt size, Bool fill, Int resolution)C
  37. {
  38. Matrix3 matrix; matrix.setUp(normal);
  39. if(fill)
  40. {
  41. Quad(pos+size*(matrix.z-matrix.x), pos+size*(matrix.x+matrix.z), pos+size*(matrix.x-matrix.z), pos+size*(-matrix.x-matrix.z)).draw(color, true);
  42. }else
  43. {
  44. if(resolution<0)resolution=16;else if(resolution<2)resolution=2;
  45. DrawPlane(color, (size*2)/resolution, resolution, pos, matrix, false);
  46. }
  47. }
  48. void Plane::drawInfiniteBySize(C Color &color, Flt cell_size)C
  49. {
  50. Matrix3 matrix; matrix.setUp(normal);
  51. Int resolution=Ceil2(Ceil((D.viewRange()*2)/cell_size)); // must be multiple of 2
  52. Vec cam_delta =CamMatrix.pos/ObjMatrix-pos,
  53. aligned =pos+matrix.x*AlignRound(Dot(cam_delta, matrix.x), cell_size)
  54. +matrix.z*AlignRound(Dot(cam_delta, matrix.z), cell_size);
  55. DrawPlane(color, cell_size, resolution, aligned, matrix, true);
  56. }
  57. void Plane::drawInfiniteByResolution(C Color &color, Int resolution)C
  58. {
  59. if(resolution<0)resolution=32;else if(resolution<2)resolution=2;
  60. Matrix3 matrix; matrix.setUp(normal);
  61. Flt cell_size=(D.viewRange()*2)/resolution;
  62. Vec cam_delta=CamMatrix.pos/ObjMatrix-pos,
  63. aligned =pos+matrix.x*AlignRound(Dot(cam_delta, matrix.x), cell_size)
  64. +matrix.z*AlignRound(Dot(cam_delta, matrix.z), cell_size);
  65. DrawPlane(color, cell_size, resolution, aligned, matrix, true);
  66. }
  67. /******************************************************************************/
  68. Flt DistPointPlane(C Vec2 &point, C Vec2 &plane_pos, C Vec2 &plane_normal) {return plane_normal.x*(point.x-plane_pos.x) + plane_normal.y*(point.y-plane_pos.y);}
  69. Dbl DistPointPlane(C VecD2 &point, C VecD2 &plane_pos, C VecD2 &plane_normal) {return plane_normal.x*(point.x-plane_pos.x) + plane_normal.y*(point.y-plane_pos.y);}
  70. Flt DistPointPlane(C Vec &point, C Vec &plane_pos, C Vec &plane_normal) {return plane_normal.x*(point.x-plane_pos.x) + plane_normal.y*(point.y-plane_pos.y) + plane_normal.z*(point.z-plane_pos.z);}
  71. Dbl DistPointPlane(C Vec &point, C VecD &plane_pos, C Vec &plane_normal) {return plane_normal.x*(point.x-plane_pos.x) + plane_normal.y*(point.y-plane_pos.y) + plane_normal.z*(point.z-plane_pos.z);}
  72. Dbl DistPointPlane(C VecD &point, C Vec &plane_pos, C Vec &plane_normal) {return plane_normal.x*(point.x-plane_pos.x) + plane_normal.y*(point.y-plane_pos.y) + plane_normal.z*(point.z-plane_pos.z);}
  73. Dbl DistPointPlane(C VecD &point, C VecD &plane_pos, C Vec &plane_normal) {return plane_normal.x*(point.x-plane_pos.x) + plane_normal.y*(point.y-plane_pos.y) + plane_normal.z*(point.z-plane_pos.z);}
  74. Dbl DistPointPlane(C VecD &point, C VecD &plane_pos, C VecD &plane_normal) {return plane_normal.x*(point.x-plane_pos.x) + plane_normal.y*(point.y-plane_pos.y) + plane_normal.z*(point.z-plane_pos.z);}
  75. // skip testing "Dot!=0" before division for performance reasons
  76. Flt DistPointPlaneRay(C Vec2 &point, C Vec2 &plane_normal, C Vec2 &ray) {return Dot (point, plane_normal)/Dot(ray, plane_normal);}
  77. Dbl DistPointPlaneRay(C VecD2 &point, C VecD2 &plane_normal, C VecD2 &ray) {return Dot (point, plane_normal)/Dot(ray, plane_normal);}
  78. Flt DistPointPlaneRay(C Vec &point, C Vec &plane_normal, C Vec &ray) {return Dot (point, plane_normal)/Dot(ray, plane_normal);}
  79. Dbl DistPointPlaneRay(C VecD &point, C Vec &plane_normal, C Vec &ray) {return Dot (point, plane_normal)/Dot(ray, plane_normal);}
  80. Dbl DistPointPlaneRay(C VecD &point, C VecD &plane_normal, C VecD &ray) {return Dot (point, plane_normal)/Dot(ray, plane_normal);}
  81. Flt DistPointPlaneRay(C Vec2 &point, C Vec2 &plane_pos, C Vec2 &plane_normal, C Vec2 &ray) {return DistPointPlane(point, plane_pos, plane_normal)/Dot(ray, plane_normal);}
  82. Dbl DistPointPlaneRay(C VecD2 &point, C VecD2 &plane_pos, C VecD2 &plane_normal, C VecD2 &ray) {return DistPointPlane(point, plane_pos, plane_normal)/Dot(ray, plane_normal);}
  83. Flt DistPointPlaneRay(C Vec &point, C Vec &plane_pos, C Vec &plane_normal, C Vec &ray) {return DistPointPlane(point, plane_pos, plane_normal)/Dot(ray, plane_normal);}
  84. Dbl DistPointPlaneRay(C VecD &point, C VecD &plane_pos, C Vec &plane_normal, C Vec &ray) {return DistPointPlane(point, plane_pos, plane_normal)/Dot(ray, plane_normal);}
  85. Dbl DistPointPlaneRay(C VecD &point, C VecD &plane_pos, C VecD &plane_normal, C VecD &ray) {return DistPointPlane(point, plane_pos, plane_normal)/Dot(ray, plane_normal);}
  86. Flt DistPointPlaneY(C Vec &point, C Vec &plane_normal) {return Dot (point, plane_normal)/plane_normal.y;}
  87. Dbl DistPointPlaneY(C VecD &point, C Vec &plane_normal) {return Dot (point, plane_normal)/plane_normal.y;}
  88. Dbl DistPointPlaneY(C VecD &point, C VecD &plane_normal) {return Dot (point, plane_normal)/plane_normal.y;}
  89. Flt DistPointPlaneY(C Vec &point, C Vec &plane_pos, C Vec &plane_normal) {return DistPointPlane(point, plane_pos, plane_normal)/plane_normal.y;}
  90. Dbl DistPointPlaneY(C VecD &point, C VecD &plane_pos, C Vec &plane_normal) {return DistPointPlane(point, plane_pos, plane_normal)/plane_normal.y;}
  91. Dbl DistPointPlaneY(C VecD &point, C VecD &plane_pos, C VecD &plane_normal) {return DistPointPlane(point, plane_pos, plane_normal)/plane_normal.y;}
  92. Vec2 PointOnPlane (C Vec2 &point, C Vec2 &plane_normal ) {return point-plane_normal*DistPointPlane (point, plane_normal );}
  93. VecD2 PointOnPlane (C VecD2 &point, C VecD2 &plane_normal ) {return point-plane_normal*DistPointPlane (point, plane_normal );}
  94. Vec PointOnPlane (C Vec &point, C Vec &plane_normal ) {return point-plane_normal*DistPointPlane (point, plane_normal );}
  95. VecD PointOnPlane (C VecD &point, C VecD &plane_normal ) {return point-plane_normal*DistPointPlane (point, plane_normal );}
  96. Vec2 PointOnPlane (C Vec2 &point, C Vec2 &plane_pos, C Vec2 &plane_normal ) {return point-plane_normal*DistPointPlane (point, plane_pos, plane_normal );}
  97. VecD2 PointOnPlane (C VecD2 &point, C VecD2 &plane_pos, C VecD2 &plane_normal ) {return point-plane_normal*DistPointPlane (point, plane_pos, plane_normal );}
  98. Vec PointOnPlane (C Vec &point, C Vec &plane_pos, C Vec &plane_normal ) {return point-plane_normal*DistPointPlane (point, plane_pos, plane_normal );}
  99. VecD PointOnPlane (C Vec &point, C VecD &plane_pos, C Vec &plane_normal ) {return point-plane_normal*DistPointPlane (point, plane_pos, plane_normal );}
  100. VecD PointOnPlane (C VecD &point, C Vec &plane_pos, C Vec &plane_normal ) {return point-plane_normal*DistPointPlane (point, plane_pos, plane_normal );}
  101. VecD PointOnPlane (C VecD &point, C VecD &plane_pos, C Vec &plane_normal ) {return point-plane_normal*DistPointPlane (point, plane_pos, plane_normal );}
  102. VecD PointOnPlane (C VecD &point, C VecD &plane_pos, C VecD &plane_normal ) {return point-plane_normal*DistPointPlane (point, plane_pos, plane_normal );}
  103. Vec2 PointOnPlaneRay(C Vec2 &point, C Vec2 &plane_normal, C Vec2 &ray) {return point-ray *DistPointPlaneRay(point, plane_normal, ray);}
  104. VecD2 PointOnPlaneRay(C VecD2 &point, C VecD2 &plane_normal, C VecD2 &ray) {return point-ray *DistPointPlaneRay(point, plane_normal, ray);}
  105. Vec PointOnPlaneRay(C Vec &point, C Vec &plane_normal, C Vec &ray) {return point-ray *DistPointPlaneRay(point, plane_normal, ray);}
  106. VecD PointOnPlaneRay(C VecD &point, C Vec &plane_normal, C Vec &ray) {return point-ray *DistPointPlaneRay(point, plane_normal, ray);}
  107. VecD PointOnPlaneRay(C VecD &point, C VecD &plane_normal, C VecD &ray) {return point-ray *DistPointPlaneRay(point, plane_normal, ray);}
  108. Vec2 PointOnPlaneRay(C Vec2 &point, C Vec2 &plane_pos, C Vec2 &plane_normal, C Vec2 &ray) {return point-ray *DistPointPlaneRay(point, plane_pos, plane_normal, ray);}
  109. VecD2 PointOnPlaneRay(C VecD2 &point, C VecD2 &plane_pos, C VecD2 &plane_normal, C VecD2 &ray) {return point-ray *DistPointPlaneRay(point, plane_pos, plane_normal, ray);}
  110. Vec PointOnPlaneRay(C Vec &point, C Vec &plane_pos, C Vec &plane_normal, C Vec &ray) {return point-ray *DistPointPlaneRay(point, plane_pos, plane_normal, ray);}
  111. VecD PointOnPlaneRay(C VecD &point, C VecD &plane_pos, C Vec &plane_normal, C Vec &ray) {return point-ray *DistPointPlaneRay(point, plane_pos, plane_normal, ray);}
  112. VecD PointOnPlaneRay(C VecD &point, C VecD &plane_pos, C VecD &plane_normal, C VecD &ray) {return point-ray *DistPointPlaneRay(point, plane_pos, plane_normal, ray);}
  113. Vec PointOnPlaneY(C Vec &point, C Vec &plane_normal) {return Vec (point.x, point.y-DistPointPlaneY(point, plane_normal), point.z);}
  114. VecD PointOnPlaneY(C VecD &point, C Vec &plane_normal) {return VecD(point.x, point.y-DistPointPlaneY(point, plane_normal), point.z);}
  115. VecD PointOnPlaneY(C VecD &point, C VecD &plane_normal) {return VecD(point.x, point.y-DistPointPlaneY(point, plane_normal), point.z);}
  116. Vec PointOnPlaneY(C Vec &point, C Vec &plane_pos, C Vec &plane_normal) {return Vec (point.x, point.y-DistPointPlaneY(point, plane_pos, plane_normal), point.z);}
  117. VecD PointOnPlaneY(C VecD &point, C VecD &plane_pos, C Vec &plane_normal) {return VecD(point.x, point.y-DistPointPlaneY(point, plane_pos, plane_normal), point.z);}
  118. VecD PointOnPlaneY(C VecD &point, C VecD &plane_pos, C VecD &plane_normal) {return VecD(point.x, point.y-DistPointPlaneY(point, plane_pos, plane_normal), point.z);}
  119. Flt PointOnPlane( Flt a, Flt b, Flt dist_a, Flt dist_b) {return Lerp(a, b, PointOnPlaneStep(dist_a, dist_b));}
  120. Dbl PointOnPlane( Dbl a, Dbl b, Dbl dist_a, Dbl dist_b) {return Lerp(a, b, PointOnPlaneStep(dist_a, dist_b));}
  121. Vec2 PointOnPlane(C Vec2 &a, C Vec2 &b, Flt dist_a, Flt dist_b) {return Lerp(a, b, PointOnPlaneStep(dist_a, dist_b));}
  122. VecD2 PointOnPlane(C VecD2 &a, C VecD2 &b, Dbl dist_a, Dbl dist_b) {return Lerp(a, b, PointOnPlaneStep(dist_a, dist_b));}
  123. Vec PointOnPlane(C Vec &a, C Vec &b, Flt dist_a, Flt dist_b) {return Lerp(a, b, PointOnPlaneStep(dist_a, dist_b));}
  124. VecD PointOnPlane(C VecD &a, C VecD &b, Dbl dist_a, Dbl dist_b) {return Lerp(a, b, PointOnPlaneStep(dist_a, dist_b));}
  125. /******************************************************************************/
  126. Bool SweepPointPlane(C Vec2 &point, C Vec2 &move, C Plane2 &plane, Flt *hit_frac, Vec2 *hit_normal, Vec2 *hit_pos, Bool two_sided)
  127. {
  128. Flt way =Dot (move , plane.normal); if(two_sided ? (way==0) : (way>=0))return false; // we ignore cases when the point is already on the plane to allow movement along the plane surface, in 'two_sided' mode we skip if we move along the plane surface "way==0", in one sided mode we skip if we move along the plane surface "way==0" or in the same direction as plane normal "way>0"
  129. Flt dist=Dist(point, plane );
  130. if((way<0) // if we're going towards the plane (against plane normal)
  131. ? (dist<0 || dist+way>0) // distance is already below the plane OR even after movement we still haven't reached the plane
  132. : (dist>0 || dist+way<0)) // distance is already above the plane OR even after movement we still haven't reached the plane
  133. return false;
  134. //if(hit_frac || hit_pos || hit_normal) skip testing this as it's faster this way
  135. {
  136. Flt frac=-dist/way;
  137. if(hit_frac ) *hit_frac = frac;
  138. if(hit_pos ) *hit_pos =point+frac*move;
  139. if(hit_normal){*hit_normal=plane.normal; if(way>0)hit_normal->chs();}
  140. }
  141. return true;
  142. }
  143. Bool SweepPointPlane(C VecD2 &point, C VecD2 &move, C PlaneD2 &plane, Dbl *hit_frac, VecD2 *hit_normal, VecD2 *hit_pos, Bool two_sided)
  144. {
  145. Dbl way =Dot (move , plane.normal); if(two_sided ? (way==0) : (way>=0))return false; // we ignore cases when the point is already on the plane to allow movement along the plane surface, in 'two_sided' mode we skip if we move along the plane surface "way==0", in one sided mode we skip if we move along the plane surface "way==0" or in the same direction as plane normal "way>0"
  146. Dbl dist=Dist(point, plane );
  147. if((way<0) // if we're going towards the plane (against plane normal)
  148. ? (dist<0 || dist+way>0) // distance is already below the plane OR even after movement we still haven't reached the plane
  149. : (dist>0 || dist+way<0)) // distance is already above the plane OR even after movement we still haven't reached the plane
  150. return false;
  151. //if(hit_frac || hit_pos || hit_normal) skip testing this as it's faster this way
  152. {
  153. Dbl frac=-dist/way;
  154. if(hit_frac ) *hit_frac = frac;
  155. if(hit_pos ) *hit_pos =point+frac*move;
  156. if(hit_normal){*hit_normal=plane.normal; if(way>0)hit_normal->chs();}
  157. }
  158. return true;
  159. }
  160. Bool SweepPointPlane(C Vec &point, C Vec &move, C Plane &plane, Flt *hit_frac, Vec *hit_normal, Vec *hit_pos, Bool two_sided)
  161. {
  162. Flt way =Dot (move , plane.normal); if(two_sided ? (way==0) : (way>=0))return false; // we ignore cases when the point is already on the plane to allow movement along the plane surface, in 'two_sided' mode we skip if we move along the plane surface "way==0", in one sided mode we skip if we move along the plane surface "way==0" or in the same direction as plane normal "way>0"
  163. Flt dist=Dist(point, plane );
  164. if((way<0) // if we're going towards the plane (against plane normal)
  165. ? (dist<0 || dist+way>0) // distance is already below the plane OR even after movement we still haven't reached the plane
  166. : (dist>0 || dist+way<0)) // distance is already above the plane OR even after movement we still haven't reached the plane
  167. return false;
  168. //if(hit_frac || hit_pos || hit_normal) skip testing this as it's faster this way
  169. {
  170. Flt frac=-dist/way;
  171. if(hit_frac ) *hit_frac = frac;
  172. if(hit_pos ) *hit_pos =point+frac*move;
  173. if(hit_normal){*hit_normal=plane.normal; if(way>0)hit_normal->chs();}
  174. }
  175. return true;
  176. }
  177. Bool SweepPointPlane(C VecD &point, C VecD &move, C PlaneD &plane, Dbl *hit_frac, VecD *hit_normal, VecD *hit_pos, Bool two_sided)
  178. {
  179. Dbl way =Dot (move , plane.normal); if(two_sided ? (way==0) : (way>=0))return false; // we ignore cases when the point is already on the plane to allow movement along the plane surface, in 'two_sided' mode we skip if we move along the plane surface "way==0", in one sided mode we skip if we move along the plane surface "way==0" or in the same direction as plane normal "way>0"
  180. Dbl dist=Dist(point, plane );
  181. if((way<0) // if we're going towards the plane (against plane normal)
  182. ? (dist<0 || dist+way>0) // distance is already below the plane OR even after movement we still haven't reached the plane
  183. : (dist>0 || dist+way<0)) // distance is already above the plane OR even after movement we still haven't reached the plane
  184. return false;
  185. //if(hit_frac || hit_pos || hit_normal) skip testing this as it's faster this way
  186. {
  187. Dbl frac=-dist/way;
  188. if(hit_frac ) *hit_frac = frac;
  189. if(hit_pos ) *hit_pos =point+frac*move;
  190. if(hit_normal){*hit_normal=plane.normal; if(way>0)hit_normal->chs();}
  191. }
  192. return true;
  193. }
  194. /******************************************************************************/
  195. void SlideMovement(Vec2 &move, C Vec2 *normal, Int normals)
  196. {
  197. Flt dist;
  198. Int find=-1; REP(normals)
  199. {
  200. Flt d=Dot(move, normal[i]);
  201. if( d<0)if(find<0 || d<dist){find=i; dist=d;}
  202. }
  203. if(find>=0)
  204. {
  205. move-=(dist-EPS)*normal[find];
  206. REP(normals)if(i!=find && Dot(move, normal[i])<0 && Dot(normal[i], normal[find])<1-EPS){move.zero(); return;}
  207. }
  208. }
  209. /******************************************************************************/
  210. void SlideMovement(Vec &move, C Vec *normal, Int normals)
  211. {
  212. Vec slide;
  213. Bool hit =false,
  214. hit0=false;
  215. REPD(i0, normals)
  216. {
  217. Flt d=Dot(move, normal[i0]); if(d<0)
  218. {
  219. hit0 =true;
  220. Bool hit1 =false;
  221. Vec slide0=move-(d-EPS)*normal[i0];
  222. REPD(i1, normals)if(i0!=i1 && Dot(slide0, normal[i1])<0 && Dot(normal[i0], normal[i1])<1-EPS)
  223. {
  224. hit1 =true;
  225. Bool hit2 =false;
  226. Vec slide1 =CrossN(normal[i0], normal[i1]);
  227. slide1*=Dot (move , slide1 );
  228. REPD(i2, normals)if(i0!=i2 && i1!=i2 && Dot(slide1, normal[i2])<0 && Dot(normal[i0], normal[i2])<1-EPS && Dot(normal[i1], normal[i2])<1-EPS)
  229. {
  230. hit2=true;
  231. break;
  232. }
  233. if(!hit2)
  234. {
  235. if(!hit || slide1.length2()>slide.length2()){hit=true; slide=slide1;}
  236. }
  237. }
  238. if(!hit1)
  239. {
  240. if(!hit || slide0.length2()>slide.length2()){hit=true; slide=slide0;}
  241. }
  242. }
  243. }
  244. if(hit0)
  245. {
  246. if(hit)move=slide;else move.zero();
  247. }
  248. }
  249. /******************************************************************************/
  250. }
  251. /******************************************************************************/