Ball.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. /******************************************************************************/
  5. #define SCALE 1.5f // max assumed stretch (for example if the original box is set to a character in rest pose, but due to animation it moves its arms around, then the box after animation might be bigger than original non-animated box, this allows to specify max allowed scale of the original box)
  6. /******************************************************************************
  7. Ball& Ball::setAnimated(C Box &box, C Matrix &matrix)
  8. {
  9. r =box.size ().length()*matrix.x.length()*(0.5f*SCALE);
  10. pos=box.center() *matrix;
  11. return T;
  12. }
  13. Ball& Ball::setAnimated(C Box &box, C AnimatedSkeleton &anim_skel)
  14. {
  15. r =box.size ().length()*anim_skel.scale ()*(0.5f*SCALE);
  16. pos=box.center() *anim_skel.matrix();
  17. return T;
  18. }
  19. /******************************************************************************/
  20. Ball& Ball::setAnimated(C Extent &ext, C Matrix &matrix)
  21. {
  22. r =ext.ext.length()*matrix.x.length()*SCALE;
  23. pos=ext.pos *matrix;
  24. return T;
  25. }
  26. Ball& Ball::setAnimated(C Extent &ext, C AnimatedSkeleton &anim_skel)
  27. {
  28. r =ext.ext.length()*anim_skel.scale ()*SCALE;
  29. pos=ext.pos *anim_skel.matrix();
  30. return T;
  31. }
  32. /******************************************************************************/
  33. Ball::Ball(C Extent &ext ) {set( ext.ext .length() , ext .pos );}
  34. Ball::Ball(C Box &box ) {set( box.size().length()*0.5f, box .center());}
  35. Ball::Ball(C OBox &obox ) {set(obox.box.size().length()*0.5f, obox .center());}
  36. Ball::Ball(C Capsule &capsule) {set( capsule.h*0.5f, capsule.pos );}
  37. Ball::Ball(C Shape &shape )
  38. {
  39. switch(shape.type)
  40. {
  41. case SHAPE_BOX : T=shape.box ; break;
  42. case SHAPE_OBOX : T=shape.obox ; break;
  43. case SHAPE_BALL : T=shape.ball ; break;
  44. case SHAPE_CAPSULE: T=shape.capsule; break;
  45. }
  46. }
  47. Ball::Ball(C MeshBase &mesh) {from(mesh.vtx.pos(), mesh.vtxs());}
  48. Ball& Ball::operator*=( Flt f) {pos*=f; r*=f; return T;}
  49. Ball& Ball::operator/=( Flt f) {pos/=f; r/=f; return T;}
  50. Ball& Ball::operator*=(C Matrix3 &m)
  51. {
  52. pos*=m;
  53. r *=m.maxScale();
  54. return T;
  55. }
  56. Ball& Ball::operator*=(C Matrix &m)
  57. {
  58. pos*=m;
  59. r *=m.maxScale();
  60. return T;
  61. }
  62. Ball& Ball::operator/=(C Matrix3 &m)
  63. {
  64. pos/=m;
  65. r /=m.maxScale();
  66. return T;
  67. }
  68. Ball& Ball::operator/=(C Matrix &m)
  69. {
  70. pos/=m;
  71. r /=m.maxScale();
  72. return T;
  73. }
  74. /******************************************************************************/
  75. Bool Ball::from(C Vec *point, Int points)
  76. {
  77. Box box; if(box.from(point, points))
  78. {
  79. pos=box.center();
  80. Flt dist2=0; REP(points)MAX(dist2, Dist2(point[i], pos));
  81. r=SqrtFast(dist2);
  82. return true;
  83. }
  84. zero(); return false;
  85. }
  86. Bool Ball::from(C Vec *point, Int points, C Matrix &matrix)
  87. {
  88. Box box; if(box.from(point, points))
  89. {
  90. pos=box.center()*matrix;
  91. Flt dist2=0; REP(points)MAX(dist2, Dist2(point[i]*matrix, pos));
  92. r=SqrtFast(dist2);
  93. return true;
  94. }
  95. zero(); return false;
  96. }
  97. /******************************************************************************/
  98. Vec Ball::nearest(C Vec &normal)C {return pos-normal*r;}
  99. /******************************************************************************/
  100. void Ball::drawVI(Bool fill, C VecI2 &resolution)C
  101. {
  102. Int res_x=((resolution.x<0) ? 24 : ((resolution.x<3) ? 3 : resolution.x)),
  103. res_y=((resolution.y<0) ? 24 : ((resolution.y<3) ? 3 : resolution.y));
  104. Flt y1_sr=r,
  105. y1_cr=0;
  106. REPD(y, res_y-1)
  107. {
  108. Flt y2_cr, y2_sr; CosSin(y2_cr, y2_sr, -PI_2+PI*y/(res_y-1)); y2_sr*=r; y2_cr*=r;
  109. Flt x1_s=0,
  110. x1_c=1;
  111. REPD(x, res_x)
  112. {
  113. Flt x2_c, x2_s; CosSin(x2_c, x2_s, (PI2*x)/res_x);
  114. if(fill)
  115. {
  116. VI.quad(pos+Vec(x2_c*y1_cr, y1_sr, x2_s*y1_cr),
  117. pos+Vec(x1_c*y1_cr, y1_sr, x1_s*y1_cr),
  118. pos+Vec(x1_c*y2_cr, y2_sr, x1_s*y2_cr),
  119. pos+Vec(x2_c*y2_cr, y2_sr, x2_s*y2_cr));
  120. }else
  121. {
  122. VI.line(pos+Vec(x1_c*y1_cr, y1_sr, x1_s*y1_cr), pos+Vec(x1_c*y2_cr, y2_sr, x1_s*y2_cr));
  123. if(y)VI.line(pos+Vec(x1_c*y2_cr, y2_sr, x1_s*y2_cr), pos+Vec(x2_c*y2_cr, y2_sr, x2_s*y2_cr));
  124. }
  125. x1_s=x2_s;
  126. x1_c=x2_c;
  127. }
  128. y1_sr=y2_sr;
  129. y1_cr=y2_cr;
  130. }
  131. }
  132. void Ball::draw(C Color &color, Bool fill, C VecI2 &resolution)C
  133. {
  134. VI.color(color); drawVI(fill, resolution);
  135. VI.end ( );
  136. }
  137. void Ball::drawAngle(C Color &color, Flt from, Flt to, C Vec &up, Bool fill, C VecI2 &resolution)C
  138. {
  139. to-=from;
  140. Matrix m; m.setPosUp(VecZero, up).scale(r).move(pos);
  141. Int res_x=((resolution.x<0) ? 24 : ((resolution.x<3) ? 3 : resolution.x)),
  142. res_y=((resolution.y<0) ? 24 : ((resolution.y<3) ? 3 : resolution.y));
  143. Flt y1_cr, y1_sr; CosSin(y1_cr, y1_sr, from+to);
  144. VI.color(color);
  145. REPD(y, res_y-1)
  146. {
  147. Flt y2_cr, y2_sr; CosSin(y2_cr, y2_sr, from+to*y/(res_y-1));
  148. Flt x1_s=0,
  149. x1_c=1;
  150. REPD(x, res_x)
  151. {
  152. Flt x2_c, x2_s; CosSin(x2_c, x2_s, (PI2*x)/res_x);
  153. if(fill)
  154. {
  155. VI.quad(Vec(x2_c*y1_cr, y1_sr, x2_s*y1_cr)*m,
  156. Vec(x1_c*y1_cr, y1_sr, x1_s*y1_cr)*m,
  157. Vec(x1_c*y2_cr, y2_sr, x1_s*y2_cr)*m,
  158. Vec(x2_c*y2_cr, y2_sr, x2_s*y2_cr)*m);
  159. }else
  160. {
  161. VI.line(Vec(x1_c*y1_cr, y1_sr, x1_s*y1_cr)*m, Vec(x1_c*y2_cr, y2_sr, x1_s*y2_cr)*m);
  162. if(y)VI.line(Vec(x1_c*y2_cr, y2_sr, x1_s*y2_cr)*m, Vec(x2_c*y2_cr, y2_sr, x2_s*y2_cr)*m);
  163. }
  164. x1_s=x2_s;
  165. x1_c=x2_c;
  166. }
  167. y1_sr=y2_sr;
  168. y1_cr=y2_cr;
  169. }
  170. VI.end();
  171. }
  172. void Ball::draw2(C Color &color, Bool fill, Int resolution)C
  173. {
  174. Matrix m[6]; REP(6)m[i].setPosOrient(pos, DIR_ENUM(i));
  175. m[DIR_BACK].y.chs();
  176. m[DIR_LEFT].y.chs();
  177. m[DIR_DOWN].x.set(0, 0,-1);
  178. m[DIR_DOWN].y.set(1, 0, 0);
  179. m[DIR_DOWN].z.set(0,-1, 0);
  180. if(resolution<0)resolution=12;else if(resolution<1)resolution=1;
  181. Vec t(-resolution/2.0f, -resolution/2.0f, resolution/2.0f);
  182. VI.color(color);
  183. REPD(y, resolution)
  184. REPD(x, resolution)
  185. {
  186. Vec bp[4]=
  187. {
  188. Vec(x , y+1, 0),
  189. Vec(x+1, y+1, 0),
  190. Vec(x+1, y , 0),
  191. Vec(x , y , 0),
  192. };
  193. REP(4){bp[i]+=t; bp[i].setLength(r);}
  194. REPD(s, 6)
  195. {
  196. Vec p[4]; Copy(p, bp); Transform(p, m[s], 4);
  197. if(fill)VI.quad(p[0], p[1], p[2], p[3]);else
  198. {
  199. VI.line(p[0], p[1]);
  200. VI.line(p[0], p[3]);
  201. }
  202. }
  203. }
  204. VI.end();
  205. }
  206. /******************************************************************************/
  207. Ball Avg(C Ball &a, C Ball &b) {return Ball(Avg(a.r, b.r), Avg(a.pos, b.pos));}
  208. /******************************************************************************/
  209. Flt Dist(C Vec &point, C Ball &ball)
  210. {
  211. return Max(0, Dist(point, ball.pos)-ball.r);
  212. }
  213. Flt Dist(C Edge &edge, C Ball &ball)
  214. {
  215. return Max(0, Dist(ball.pos, edge)-ball.r);
  216. }
  217. Flt Dist(C Tri &tri, C Ball &ball)
  218. {
  219. return Max(0, Dist(ball.pos, tri)-ball.r);
  220. }
  221. Flt Dist(C Box &box, C Ball &ball)
  222. {
  223. Flt dist2=0;
  224. if(ball.pos.x<box.min.x)dist2+=Sqr(ball.pos.x-box.min.x);else
  225. if(ball.pos.x>box.max.x)dist2+=Sqr(ball.pos.x-box.max.x);
  226. if(ball.pos.y<box.min.y)dist2+=Sqr(ball.pos.y-box.min.y);else
  227. if(ball.pos.y>box.max.y)dist2+=Sqr(ball.pos.y-box.max.y);
  228. if(ball.pos.z<box.min.z)dist2+=Sqr(ball.pos.z-box.min.z);else
  229. if(ball.pos.z>box.max.z)dist2+=Sqr(ball.pos.z-box.max.z);
  230. return Max(0, SqrtFast(dist2)-ball.r);
  231. }
  232. Flt Dist(C OBox &obox, C Ball &ball)
  233. {
  234. Ball temp=ball; temp.pos.divNormalized(obox.matrix);
  235. return Dist(obox.box, temp);
  236. }
  237. Flt Dist(C Ball &a, C Ball &b)
  238. {
  239. return Max(0, Dist(a.pos, b.pos)-a.r-b.r);
  240. }
  241. Flt DistBallPlane(C Ball &ball, C Vec &plane, C Vec &normal)
  242. {
  243. return DistPointPlane(ball.pos, plane, normal)-ball.r;
  244. }
  245. Dbl DistBallPlane(C Ball &ball, C VecD &plane, C Vec &normal)
  246. {
  247. return DistPointPlane(ball.pos, plane, normal)-ball.r;
  248. }
  249. Dbl DistBallPlane(C BallM &ball, C VecD &plane, C Vec &normal)
  250. {
  251. return DistPointPlane(ball.pos, plane, normal)-ball.r;
  252. }
  253. /******************************************************************************/
  254. Bool Cuts(C Vec &point, C Ball &ball)
  255. {
  256. return Dist2(point, ball.pos)<=Sqr(ball.r);
  257. }
  258. Bool Cuts(C VecD &point, C Ball &ball)
  259. {
  260. return Dist2(point, ball.pos)<=Sqr(ball.r);
  261. }
  262. Bool Cuts(C VecD &point, C BallM &ball)
  263. {
  264. return Dist2(point, ball.pos)<=Sqr(ball.r);
  265. }
  266. Bool Cuts(C Edge &edge, C Ball &ball)
  267. {
  268. return Dist(ball.pos, edge)<=ball.r;
  269. }
  270. Bool Cuts(C Tri &tri, C Ball &ball)
  271. {
  272. return Dist(ball.pos, tri)<=ball.r;
  273. }
  274. Bool Cuts(C Ball &a, C Ball &b)
  275. {
  276. return Dist2(a.pos, b.pos)<=Sqr(a.r+b.r);
  277. }
  278. Bool Cuts(C Box &box, C Ball &ball)
  279. {
  280. #if 1 // fastest
  281. if(ball.pos.x<box.min.x-ball.r || ball.pos.x>box.max.x+ball.r)return false;
  282. if(ball.pos.y<box.min.y-ball.r || ball.pos.y>box.max.y+ball.r)return false;
  283. if(ball.pos.z<box.min.z-ball.r || ball.pos.z>box.max.z+ball.r)return false;
  284. Flt dist2=0;
  285. if(ball.pos.x<box.min.x)dist2 =Sqr(ball.pos.x-box.min.x);else
  286. if(ball.pos.x>box.max.x)dist2 =Sqr(ball.pos.x-box.max.x);
  287. if(ball.pos.y<box.min.y)dist2+=Sqr(ball.pos.y-box.min.y);else
  288. if(ball.pos.y>box.max.y)dist2+=Sqr(ball.pos.y-box.max.y);
  289. if(ball.pos.z<box.min.z)dist2+=Sqr(ball.pos.z-box.min.z);else
  290. if(ball.pos.z>box.max.z)dist2+=Sqr(ball.pos.z-box.max.z);
  291. return dist2<=Sqr(ball.r);
  292. #elif 1 // medium
  293. Flt dist2=0, r2=Sqr(ball.r);
  294. if(ball.pos.x<box.min.x){dist2 =Sqr(box.min.x-ball.pos.x); if(dist2>r2)return false;}else
  295. if(ball.pos.x>box.max.x){dist2 =Sqr(ball.pos.x-box.max.x); if(dist2>r2)return false;}
  296. if(ball.pos.y<box.min.y){dist2+=Sqr(box.min.y-ball.pos.y); if(dist2>r2)return false;}else
  297. if(ball.pos.y>box.max.y){dist2+=Sqr(ball.pos.y-box.max.y); if(dist2>r2)return false;}
  298. if(ball.pos.z<box.min.z){dist2+=Sqr(box.min.z-ball.pos.z); if(dist2>r2)return false;}else
  299. if(ball.pos.z>box.max.z){dist2+=Sqr(ball.pos.z-box.max.z); if(dist2>r2)return false;}
  300. return true;
  301. #else // slowest
  302. Flt dist2=0, d;
  303. if(ball.pos.x<box.min.x){d=box.min.x-ball.pos.x; if(d>ball.r)return false; dist2 =Sqr(d);}else
  304. if(ball.pos.x>box.max.x){d=ball.pos.x-box.max.x; if(d>ball.r)return false; dist2 =Sqr(d);}
  305. if(ball.pos.y<box.min.y){d=box.min.y-ball.pos.y; if(d>ball.r)return false; dist2+=Sqr(d);}else
  306. if(ball.pos.y>box.max.y){d=ball.pos.y-box.max.y; if(d>ball.r)return false; dist2+=Sqr(d);}
  307. if(ball.pos.z<box.min.z){d=box.min.z-ball.pos.z; if(d>ball.r)return false; dist2+=Sqr(d);}else
  308. if(ball.pos.z>box.max.z){d=ball.pos.z-box.max.z; if(d>ball.r)return false; dist2+=Sqr(d);}
  309. return dist2<=Sqr(ball.r);
  310. #endif
  311. }
  312. Bool Cuts(C Extent &ext, C Ball &ball)
  313. {
  314. #if 1 // faster
  315. return Dist2(Max(0, Abs(ext.pos.x-ball.pos.x)-ext.ext.x),
  316. Max(0, Abs(ext.pos.y-ball.pos.y)-ext.ext.y),
  317. Max(0, Abs(ext.pos.z-ball.pos.z)-ext.ext.z))<=Sqr(ball.r);
  318. #else // slower
  319. Flt dist2=0, d;
  320. d=Abs(ext.pos.x-ball.pos.x)-ext.ext.x; if(d>0)dist2 =Sqr(d);
  321. d=Abs(ext.pos.y-ball.pos.y)-ext.ext.y; if(d>0)dist2+=Sqr(d);
  322. d=Abs(ext.pos.z-ball.pos.z)-ext.ext.z; if(d>0)dist2+=Sqr(d);
  323. return dist2<=Sqr(ball.r);
  324. #endif
  325. }
  326. Bool Cuts(C OBox &obox, C Ball &ball)
  327. {
  328. Ball temp; // 'ball' in 'obox' space
  329. temp.r=ball.r;
  330. temp.pos.fromDivNormalized(ball.pos, obox.matrix);
  331. return Cuts(obox.box, temp);
  332. }
  333. /******************************************************************************/
  334. Int CutsStrBall(C Vec &str_pos, C Vec &str_dir, C Ball &ball, Vec *contact_a, Vec *contact_b)
  335. {
  336. Vec p=PointOnPlane(str_pos, ball.pos, str_dir);
  337. Flt s=Dist (p , ball.pos )/ball.r;
  338. if(s> 1)return 0;
  339. if(s==1){if(contact_a)*contact_a=p; return 1;}
  340. if(contact_a || contact_b)
  341. {
  342. s=Sqrt(1-s*s)*ball.r;
  343. if(contact_a)*contact_a=p-s*str_dir;
  344. if(contact_b)*contact_b=p+s*str_dir;
  345. }
  346. return 2;
  347. }
  348. Int CutsEdgeBall(C Vec &edge_start, C Vec &edge_end, C Ball &ball, Vec *contact_a, Vec *contact_b)
  349. {
  350. Vec c[2], dir=!(edge_end-edge_start);
  351. if(Int hit=CutsStrBall(edge_start, dir, ball, &c[0], &c[1]))
  352. {
  353. Bool in[2]={(hit>=1), (hit>=2)};
  354. REP(2)if(in[i])if(DistPointPlane(c[i], edge_start, dir)<0 || DistPointPlane(c[i], edge_end, dir)>0)in[i]=false;
  355. if(in[0] && in[1]){if(contact_a)*contact_a=c[ 0]; if(contact_b)*contact_b=c[1]; return 2;}
  356. if(in[0] || in[1]){if(contact_a)*contact_a=c[in[1]]; return 1;}
  357. }
  358. return 0;
  359. }
  360. /******************************************************************************/
  361. Bool Inside(C Box &a, C Ball &b)
  362. {
  363. #if 0 // this is slower
  364. return Dist2(Max(Abs(a.max.x-b.pos.x), Abs(a.min.x-b.pos.x)),
  365. Max(Abs(a.max.y-b.pos.y), Abs(a.min.y-b.pos.y)),
  366. Max(Abs(a.max.z-b.pos.z), Abs(a.min.z-b.pos.z)))<=Sqr(b.r);
  367. #else // this is faster
  368. return Max(Sqr(a.max.x-b.pos.x), Sqr(a.min.x-b.pos.x))
  369. +Max(Sqr(a.max.y-b.pos.y), Sqr(a.min.y-b.pos.y))
  370. +Max(Sqr(a.max.z-b.pos.z), Sqr(a.min.z-b.pos.z))<=Sqr(b.r);
  371. #endif
  372. }
  373. Bool Inside(C Extent &a, C Ball &b)
  374. {
  375. return Dist2(((a.pos.x>b.pos.x) ? a.maxX() : a.minX())-b.pos.x,
  376. ((a.pos.y>b.pos.y) ? a.maxY() : a.minY())-b.pos.y,
  377. ((a.pos.z>b.pos.z) ? a.maxZ() : a.minZ())-b.pos.z)<=Sqr(b.r);
  378. }
  379. /******************************************************************************/
  380. Bool SweepPointBall(C Vec &point, C Vec &move, C Ball &ball, Flt *hit_frac, Vec *hit_normal)
  381. {
  382. Vec dir =move; Flt length=dir.normalize();
  383. Vec p =PointOnPlane(point, ball.pos, dir);
  384. Flt s =Dist(p, ball.pos)/ball.r; if(s>1)return false;
  385. p -=dir*(CosSin(s)*ball.r);
  386. Flt dist=DistPointPlane(p, point, dir); if(dist<0 || dist>length)return false;
  387. if(hit_frac )*hit_frac =dist/length;
  388. if(hit_normal)*hit_normal=(p-ball.pos)/ball.r;
  389. return true;
  390. }
  391. Bool SweepPointBall(C VecD &point, C VecD &move, C BallD &ball, Dbl *hit_frac, VecD *hit_normal)
  392. {
  393. VecD dir =move; Dbl length=dir.normalize();
  394. VecD p =PointOnPlane(point, ball.pos, dir);
  395. Dbl s =Dist(p, ball.pos)/ball.r; if(s>1)return false;
  396. p -=dir*(CosSin(s)*ball.r);
  397. Dbl dist=DistPointPlane(p, point, dir); if(dist<0 || dist>length)return false;
  398. if(hit_frac )*hit_frac =dist/length;
  399. if(hit_normal)*hit_normal=(p-ball.pos)/ball.r;
  400. return true;
  401. }
  402. /******************************************************************************/
  403. Bool SweepBallPoint(C Ball &ball, C Vec &move, C Vec &point, Flt *hit_frac, Vec *hit_normal)
  404. {
  405. Vec dir =move; Flt length=dir.normalize();
  406. Vec p =PointOnPlane(ball.pos, point, dir);
  407. Flt s =Dist(p, point)/ball.r; if(s>1)return false;
  408. p -=dir*(CosSin(s)*ball.r);
  409. Flt dist=DistPointPlane(p, ball.pos, dir); if(dist<0 || dist>length)return false;
  410. if(hit_frac )*hit_frac =dist/length;
  411. if(hit_normal)*hit_normal=(p-point)/ball.r;
  412. return true;
  413. }
  414. Bool SweepBallPoint(C BallD &ball, C VecD &move, C VecD &point, Dbl *hit_frac, VecD *hit_normal)
  415. {
  416. VecD dir =move; Dbl length=dir.normalize();
  417. VecD p =PointOnPlane(ball.pos, point, dir);
  418. Dbl s =Dist(p, point)/ball.r; if(s>1)return false;
  419. p -=dir*(CosSin(s)*ball.r);
  420. Dbl dist=DistPointPlane(p, ball.pos, dir); if(dist<0 || dist>length)return false;
  421. if(hit_frac )*hit_frac =dist/length;
  422. if(hit_normal)*hit_normal=(p-point)/ball.r;
  423. return true;
  424. }
  425. /******************************************************************************/
  426. Bool SweepBallEdge(C Ball &ball, C Vec &move, C Edge &edge, Flt *hit_frac, Vec *hit_normal) // safe in case 'edge' is zero length
  427. {
  428. Int point_test;
  429. Vec dir=edge.delta(); if(dir.normalize()) // check if 'edge' has length
  430. {
  431. Matrix matrix; matrix. setPosDir(edge.p[0], dir );
  432. Circle circle(ball.r, matrix. convert(ball.pos , true));
  433. Vec2 move2 = matrix.orn().convert(move , true) ;
  434. Vec2 normal; Flt frac;
  435. if(SweepCirclePoint(circle, move2, Vec2(0), &frac, &normal))
  436. {
  437. Vec point=ball.pos+frac*move;
  438. if(DistPointPlane(point, edge.p[0], matrix.z)<0)point_test=0;else
  439. if(DistPointPlane(point, edge.p[1], matrix.z)>0)point_test=1;else
  440. {
  441. if(hit_frac )*hit_frac =frac;
  442. if(hit_normal)*hit_normal=matrix.orn().convert(normal);
  443. return true;
  444. }
  445. }else point_test=Closer(ball.pos, edge.p[0], edge.p[1]);
  446. }else point_test=0; // if 'edge' is zero length then check first point
  447. return SweepBallPoint(ball, move, edge.p[point_test], hit_frac, hit_normal);
  448. }
  449. Bool SweepBallEdge(C BallD &ball, C VecD &move, C EdgeD &edge, Dbl *hit_frac, VecD *hit_normal) // safe in case 'edge' is zero length
  450. {
  451. Int point_test;
  452. VecD dir=edge.delta(); if(dir.normalize()) // check if 'edge' has length
  453. {
  454. MatrixD matrix; matrix. setPosDir(edge.p[0], dir );
  455. CircleD circle(ball.r, matrix. convert(ball.pos , true));
  456. VecD2 move2 = matrix.orn().convert(move , true) ;
  457. VecD2 normal; Dbl frac;
  458. if(SweepCirclePoint(circle, move2, VecD2(0), &frac, &normal))
  459. {
  460. VecD point=ball.pos+frac*move;
  461. if(DistPointPlane(point, edge.p[0], matrix.z)<0)point_test=0;else
  462. if(DistPointPlane(point, edge.p[1], matrix.z)>0)point_test=1;else
  463. {
  464. if(hit_frac )*hit_frac =frac;
  465. if(hit_normal)*hit_normal=matrix.orn().convert(normal);
  466. return true;
  467. }
  468. }else point_test=Closer(ball.pos, edge.p[0], edge.p[1]);
  469. }else point_test=0; // if 'edge' is zero length then check first point
  470. return SweepBallPoint(ball, move, edge.p[point_test], hit_frac, hit_normal);
  471. }
  472. /******************************************************************************/
  473. Bool SweepBallBall(C Ball &ball, C Vec &move, C Ball &ball2, Flt *hit_frac, Vec *hit_normal)
  474. {
  475. return SweepPointBall(ball.pos, move, Ball(ball.r+ball2.r, ball2.pos), hit_frac, hit_normal); // 'hit_normal' is OK when merging 2 balls, this was tested, it will always be in the line of ball positions when they are in contact ('ball' 'move'd by 'hit_frac')
  476. }
  477. Bool SweepBallBall(C BallD &ball, C VecD &move, C BallD &ball2, Dbl *hit_frac, VecD *hit_normal)
  478. {
  479. return SweepPointBall(ball.pos, move, BallD(ball.r+ball2.r, ball2.pos), hit_frac, hit_normal); // 'hit_normal' is OK when merging 2 balls, this was tested, it will always be in the line of ball positions when they are in contact ('ball' 'move'd by 'hit_frac')
  480. }
  481. /******************************************************************************/
  482. }
  483. /******************************************************************************/