Triangle.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. /******************************************************************************/
  5. Tri2 ::Tri2 (C TriD2 &tri) {p[0]=tri.p[0]; p[1]=tri.p[1]; p[2]=tri.p[2];}
  6. TriD2::TriD2(C Tri2 &tri) {p[0]=tri.p[0]; p[1]=tri.p[1]; p[2]=tri.p[2];}
  7. Tri ::Tri (C TriD &tri) {p[0]=tri.p[0]; p[1]=tri.p[1]; p[2]=tri.p[2]; n=tri.n ;}
  8. TriD ::TriD (C Tri &tri) {p[0]=tri.p[0]; p[1]=tri.p[1]; p[2]=tri.p[2]; setNormal();}
  9. Tri2 & Tri2 ::operator+=(C Vec2 &v) {p[0]+=v; p[1]+=v; p[2]+=v; return T;}
  10. Tri2 & Tri2 ::operator-=(C Vec2 &v) {p[0]-=v; p[1]-=v; p[2]-=v; return T;}
  11. TriD2& TriD2::operator+=(C VecD2 &v) {p[0]+=v; p[1]+=v; p[2]+=v; return T;}
  12. TriD2& TriD2::operator-=(C VecD2 &v) {p[0]-=v; p[1]-=v; p[2]-=v; return T;}
  13. Tri & Tri ::operator+=(C Vec &v) {p[0]+=v; p[1]+=v; p[2]+=v; return T;}
  14. Tri & Tri ::operator-=(C Vec &v) {p[0]-=v; p[1]-=v; p[2]-=v; return T;}
  15. TriD & TriD ::operator+=(C VecD &v) {p[0]+=v; p[1]+=v; p[2]+=v; return T;}
  16. TriD & TriD ::operator-=(C VecD &v) {p[0]-=v; p[1]-=v; p[2]-=v; return T;}
  17. Tri2 & Tri2 ::operator*=( Flt r) {p[0]*=r; p[1]*=r; p[2]*=r; return T;}
  18. Tri2 & Tri2 ::operator/=( Flt r) {p[0]/=r; p[1]/=r; p[2]/=r; return T;}
  19. TriD2& TriD2::operator*=( Dbl r) {p[0]*=r; p[1]*=r; p[2]*=r; return T;}
  20. TriD2& TriD2::operator/=( Dbl r) {p[0]/=r; p[1]/=r; p[2]/=r; return T;}
  21. Tri & Tri ::operator*=( Flt r) {p[0]*=r; p[1]*=r; p[2]*=r; return T;}
  22. Tri & Tri ::operator/=( Flt r) {p[0]/=r; p[1]/=r; p[2]/=r; return T;}
  23. TriD & TriD ::operator*=( Dbl r) {p[0]*=r; p[1]*=r; p[2]*=r; return T;}
  24. TriD & TriD ::operator/=( Dbl r) {p[0]/=r; p[1]/=r; p[2]/=r; return T;}
  25. /******************************************************************************/
  26. Tri& Tri::set(C Vec &p0, C Vec &p1, C Vec &p2, C Vec *nrm)
  27. {
  28. p[0]=p0;
  29. p[1]=p1;
  30. p[2]=p2;
  31. if(nrm)n=*nrm;else setNormal();
  32. return T;
  33. }
  34. TriD& TriD::set(C VecD &p0, C VecD &p1, C VecD &p2, C VecD *nrm)
  35. {
  36. p[0]=p0;
  37. p[1]=p1;
  38. p[2]=p2;
  39. if(nrm)n=*nrm;else setNormal();
  40. return T;
  41. }
  42. /******************************************************************************/
  43. Tri2& Tri2::setArrow(Flt direction, Flt angle)
  44. {
  45. CosSin(p[0].x, p[0].y, direction); direction+=PI; angle*=0.5f;
  46. CosSin(p[1].x, p[1].y, direction+angle);
  47. CosSin(p[2].x, p[2].y, direction-angle);
  48. return T;
  49. }
  50. /******************************************************************************/
  51. Flt Tri2 ::area()C {return 0.5f*Abs(Cross(p[1]-p[0], p[2]-p[0]));}
  52. Dbl TriD2::area()C {return 0.5 *Abs(Cross(p[1]-p[0], p[2]-p[0]));}
  53. Flt Tri ::area()C {return 0.5f* Cross(p[1]-p[0], p[2]-p[0]).length();}
  54. Dbl TriD ::area()C {return 0.5 * Cross(p[1]-p[0], p[2]-p[0]).length();}
  55. /******************************************************************************/
  56. Bool Tri2::valid(Flt eps)C
  57. {
  58. return DistPointStr(p[0], p[1], !(p[2]-p[1]))>eps
  59. && DistPointStr(p[1], p[2], !(p[0]-p[2]))>eps
  60. && DistPointStr(p[2], p[0], !(p[1]-p[0]))>eps;
  61. }
  62. Bool Tri::valid(Flt eps)C
  63. {
  64. return DistPointStr(p[0], p[1], !(p[2]-p[1]))>eps
  65. && DistPointStr(p[1], p[2], !(p[0]-p[2]))>eps
  66. && DistPointStr(p[2], p[0], !(p[1]-p[0]))>eps;
  67. }
  68. /******************************************************************************/
  69. Bool Tri2 ::clockwise()C {return Cross(p[1]-p[0], p[2]-p[0])<0;}
  70. Bool TriD2::clockwise()C {return Cross(p[1]-p[0], p[2]-p[0])<0;}
  71. /******************************************************************************/
  72. Bool Tri::coplanar(C Tri &tri)C
  73. {
  74. return Abs(DistPointPlane(p[0], tri))<=EPS
  75. && Abs(DistPointPlane(p[1], tri))<=EPS
  76. && Abs(DistPointPlane(p[2], tri))<=EPS;
  77. }
  78. Bool TriD::coplanar(C TriD &tri)C
  79. {
  80. return Abs(DistPointPlane(p[0], tri))<=EPSD
  81. && Abs(DistPointPlane(p[1], tri))<=EPSD
  82. && Abs(DistPointPlane(p[2], tri))<=EPSD;
  83. }
  84. /******************************************************************************/
  85. void Tri2::circularLerp(Tri2 *tri, Int num)C
  86. {
  87. if(num>0)
  88. {
  89. tri[0 ].p[1]=p[1];
  90. tri[num-1].p[2]=p[2];
  91. tri[num-1].p[0]=p[0];
  92. Flt d01=Dist(p[0], p[1]),
  93. d02=Dist(p[0], p[2]);
  94. REP(num-1)
  95. {
  96. Flt s=Flt(i+1)/num;
  97. Vec2 t= Lerp(p[1], p[2], s) - p[0];
  98. t.setLength(Lerp(d01 , d02 , s)); t+=p[0];
  99. tri[i ].p[0]=p[0];
  100. tri[i ].p[2]=
  101. tri[i+1].p[1]=t;
  102. }
  103. }
  104. }
  105. void Tri::circularLerp(Tri *tri, Int num)C
  106. {
  107. if(num>0)
  108. {
  109. tri[0 ].p[1]=p[1];
  110. tri[num-1].p[2]=p[2];
  111. tri[num-1].p[0]=p[0];
  112. tri[num-1].n =n ;
  113. Flt d01=Dist(p[0], p[1]),
  114. d02=Dist(p[0], p[2]);
  115. REP(num-1)
  116. {
  117. Flt s=Flt(i+1)/num;
  118. Vec t= Lerp(p[1], p[2], s) - p[0];
  119. t.setLength(Lerp(d01 , d02 , s)); t+=p[0];
  120. tri[i ].p[0]=p[0];
  121. tri[i ].p[2]=
  122. tri[i+1].p[1]=t;
  123. tri[i ].n =n;
  124. }
  125. }
  126. }
  127. /******************************************************************************/
  128. void Tri2::draw(C Color &color, Bool fill)C
  129. {
  130. VI.color (color);
  131. VI.setType(VI_2D_FLAT, fill ? 0 : VI_LINE|VI_STRIP);
  132. if(Vtx2DFlat *v=(Vtx2DFlat*)VI.addVtx(fill ? 3 : 4))
  133. {
  134. if(fill)
  135. {
  136. v[0].pos=p[0];
  137. v[1].pos=p[1];
  138. v[2].pos=p[2];
  139. }else
  140. {
  141. v[0].pos=p[0];
  142. v[1].pos=p[1];
  143. v[2].pos=p[2];
  144. v[3].pos=p[0];
  145. }
  146. }
  147. VI.end();
  148. }
  149. void TriD2::draw(C Color &color, Bool fill)C
  150. {
  151. VI.color (color);
  152. VI.setType(VI_2D_FLAT, fill ? 0 : VI_LINE|VI_STRIP);
  153. if(Vtx2DFlat *v=(Vtx2DFlat*)VI.addVtx(fill ? 3 : 4))
  154. {
  155. if(fill)
  156. {
  157. v[0].pos=p[0];
  158. v[1].pos=p[1];
  159. v[2].pos=p[2];
  160. }else
  161. {
  162. v[0].pos=p[0];
  163. v[1].pos=p[1];
  164. v[2].pos=p[2];
  165. v[3].pos=p[0];
  166. }
  167. }
  168. VI.end();
  169. }
  170. void Tri::draw(C Color &color, Bool fill)C
  171. {
  172. VI.color (color);
  173. VI.setType(VI_3D_FLAT, fill ? 0 : VI_LINE|VI_STRIP);
  174. if(Vtx3DFlat *v=(Vtx3DFlat*)VI.addVtx(fill ? 3 : 4))
  175. {
  176. if(fill)
  177. {
  178. v[0].pos=p[0];
  179. v[1].pos=p[1];
  180. v[2].pos=p[2];
  181. }else
  182. {
  183. v[0].pos=p[0];
  184. v[1].pos=p[1];
  185. v[2].pos=p[2];
  186. v[3].pos=p[0];
  187. }
  188. }
  189. VI.end();
  190. }
  191. void TriD::draw(C Color &color, Bool fill)C
  192. {
  193. VI.color (color);
  194. VI.setType(VI_3D_FLAT, fill ? 0 : VI_LINE|VI_STRIP);
  195. if(Vtx3DFlat *v=(Vtx3DFlat*)VI.addVtx(fill ? 3 : 4))
  196. {
  197. if(fill)
  198. {
  199. v[0].pos=p[0];
  200. v[1].pos=p[1];
  201. v[2].pos=p[2];
  202. }else
  203. {
  204. v[0].pos=p[0];
  205. v[1].pos=p[1];
  206. v[2].pos=p[2];
  207. v[3].pos=p[0];
  208. }
  209. }
  210. VI.end();
  211. }
  212. /******************************************************************************/
  213. Vec GetNormal (C Vec &p0, C Vec &p1, C Vec &p2) {return CrossN(p1-p0, p2-p0);}
  214. VecD GetNormal (C VecD &p0, C VecD &p1, C VecD &p2) {return CrossN(p1-p0, p2-p0);}
  215. Vec GetNormalU(C Vec &p0, C Vec &p1, C Vec &p2) {return Cross (p1-p0, p2-p0);}
  216. VecD GetNormalU(C VecD &p0, C VecD &p1, C VecD &p2) {return Cross (p1-p0, p2-p0);}
  217. Vec GetNormalU( C Vec &p1, C Vec &p2) {return Cross (p1 , p2 );}
  218. Flt TriArea2(C Vec &p0, C Vec &p1, C Vec &p2) {return Cross(p1-p0, p2-p0).length();}
  219. Dbl TriArea2(C VecD &p0, C VecD &p1, C VecD &p2) {return Cross(p1-p0, p2-p0).length();}
  220. Vec GetNormalEdge(C Vec &p0, C Vec &p1) // this is called the "Newell" method
  221. {
  222. return Vec((p0.y-p1.y)*(p0.z+p1.z),
  223. (p0.z-p1.z)*(p0.x+p1.x),
  224. (p0.x-p1.x)*(p0.y+p1.y));
  225. }
  226. /******************************************************************************/
  227. Flt TriABAngle(Flt a_length, Flt b_length, Flt c_length)
  228. {
  229. if(Flt div=2*a_length*b_length)return Acos((Sqr(a_length)+Sqr(b_length)-Sqr(c_length))/div);
  230. return 0;
  231. }
  232. /******************************************************************************/
  233. Vec TriBlend(C Vec2 &p, C Tri2 &tri)
  234. {
  235. // blend.x*(x0-x2) + blend.y*(x1-x2) = x-x2
  236. // blend.x*(y0-y2) + blend.y*(y1-y2) = y-y2
  237. Vec blend; if(Solve(tri.p[0].x-tri.p[2].x, tri.p[0].y-tri.p[2].y, tri.p[1].x-tri.p[2].x, tri.p[1].y-tri.p[2].y, p.x-tri.p[2].x, p.y-tri.p[2].y, blend.x, blend.y)!=1)blend.x=blend.y=0;
  238. blend.z=1-blend.x-blend.y;
  239. return blend;
  240. }
  241. VecD TriBlend(C VecD2 &p, C TriD2 &tri)
  242. {
  243. // blend.x*(x0-x2) + blend.y*(x1-x2) = x-x2
  244. // blend.x*(y0-y2) + blend.y*(y1-y2) = y-y2
  245. VecD blend; if(Solve(tri.p[0].x-tri.p[2].x, tri.p[0].y-tri.p[2].y, tri.p[1].x-tri.p[2].x, tri.p[1].y-tri.p[2].y, p.x-tri.p[2].x, p.y-tri.p[2].y, blend.x, blend.y)!=1)blend.x=blend.y=0;
  246. blend.z=1-blend.x-blend.y;
  247. return blend;
  248. }
  249. Vec TriBlend(C Vec &p, C Tri &tri, Bool pos_on_tri_plane)
  250. {
  251. if(!pos_on_tri_plane)return TriBlend(PointOnPlane(p, tri.p[0], tri.n), tri, true);
  252. Vec blend, size=Box(tri).size();
  253. if(size.z<=size.x && size.z<=size.y) // if Z dimension is smallest
  254. {
  255. // use XY plane
  256. if(Solve(tri.p[0].x-tri.p[2].x, tri.p[0].y-tri.p[2].y, tri.p[1].x-tri.p[2].x, tri.p[1].y-tri.p[2].y, p.x-tri.p[2].x, p.y-tri.p[2].y, blend.x, blend.y)!=1)blend.x=blend.y=0;
  257. }else
  258. if(size.y<=size.x && size.y<=size.z) // if Y dimension is smallest
  259. {
  260. // use XZ plane
  261. if(Solve(tri.p[0].x-tri.p[2].x, tri.p[0].z-tri.p[2].z, tri.p[1].x-tri.p[2].x, tri.p[1].z-tri.p[2].z, p.x-tri.p[2].x, p.z-tri.p[2].z, blend.x, blend.y)!=1)blend.x=blend.y=0;
  262. }else
  263. {
  264. // use YZ plane
  265. if(Solve(tri.p[0].y-tri.p[2].y, tri.p[0].z-tri.p[2].z, tri.p[1].y-tri.p[2].y, tri.p[1].z-tri.p[2].z, p.y-tri.p[2].y, p.z-tri.p[2].z, blend.x, blend.y)!=1)blend.x=blend.y=0;
  266. }
  267. blend.z=1-blend.x-blend.y;
  268. return blend;
  269. }
  270. VecD TriBlend(C VecD &p, C TriD &tri, Bool pos_on_tri_plane)
  271. {
  272. if(!pos_on_tri_plane)return TriBlend(PointOnPlane(p, tri.p[0], tri.n), tri, true);
  273. VecD blend, size=BoxD(tri).size();
  274. if(size.z<=size.x && size.z<=size.y) // if Z dimension is smallest
  275. {
  276. // use XY plane
  277. if(Solve(tri.p[0].x-tri.p[2].x, tri.p[0].y-tri.p[2].y, tri.p[1].x-tri.p[2].x, tri.p[1].y-tri.p[2].y, p.x-tri.p[2].x, p.y-tri.p[2].y, blend.x, blend.y)!=1)blend.x=blend.y=0;
  278. }else
  279. if(size.y<=size.x && size.y<=size.z) // if Y dimension is smallest
  280. {
  281. // use XZ plane
  282. if(Solve(tri.p[0].x-tri.p[2].x, tri.p[0].z-tri.p[2].z, tri.p[1].x-tri.p[2].x, tri.p[1].z-tri.p[2].z, p.x-tri.p[2].x, p.z-tri.p[2].z, blend.x, blend.y)!=1)blend.x=blend.y=0;
  283. }else
  284. {
  285. // use YZ plane
  286. if(Solve(tri.p[0].y-tri.p[2].y, tri.p[0].z-tri.p[2].z, tri.p[1].y-tri.p[2].y, tri.p[1].z-tri.p[2].z, p.y-tri.p[2].y, p.z-tri.p[2].z, blend.x, blend.y)!=1)blend.x=blend.y=0;
  287. }
  288. blend.z=1-blend.x-blend.y;
  289. return blend;
  290. }
  291. /******************************************************************************/
  292. Vec4 TetraBlend(C Vec &p, C Vec &p0, C Vec &p1, C Vec &p2, C Vec &p3)
  293. {
  294. Vec4 blend;
  295. Vec q =p -p3,
  296. q0=p0-p3,
  297. q1=p1-p3,
  298. q2=p2-p3;
  299. Matrix3 m;
  300. m.x=q0;
  301. m.y=q1;
  302. m.z=q2;
  303. Flt det =m.determinant();
  304. m.x=q; blend.x=m.determinant();
  305. m.x=q0; m.y=q; blend.y=m.determinant();
  306. m.y=q1; m.z=q; blend.z=m.determinant();
  307. if(det)blend/=det; blend.w=1-blend.x-blend.y-blend.z;
  308. return blend;
  309. }
  310. Flt TetraVolume(C Vec &a, C Vec &b, C Vec &c, C Vec &d)
  311. {
  312. return Abs(Dot(a-d, Cross(b-d, c-d)))/6;
  313. }
  314. /******************************************************************************/
  315. static inline DIST_TYPE UpdateTypeT(DIST_TYPE type, DIST_TYPE p0, DIST_TYPE p1, DIST_TYPE edge)
  316. {
  317. switch(type)
  318. {
  319. case DIST_POINT0: return p0 ;
  320. case DIST_POINT1: return p1 ;
  321. case DIST_EDGE : return edge;
  322. default : return type;
  323. }
  324. }
  325. Flt Dist(C Vec2 &point, C Tri2 &tri, DIST_TYPE *_type)
  326. {
  327. DIST_TYPE t, type=DIST_NONE;
  328. Flt d, dist=0;
  329. UInt sign=(tri.clockwise() ? 0 : SIGN_BIT); // counter-clockwise tris require changing sign
  330. Vec2 p=point-tri.p[1]; if(Xor(DistPointPlane(p , Perp(tri.p[0]-tri.p[1])), sign)>0){d=DistPointEdge(point, tri.p[0], tri.p[1], &t); if(!type || d<dist){dist=d; type=UpdateTypeT(t, DIST_POINT0, DIST_POINT1, DIST_EDGE0);}}
  331. if(Xor(DistPointPlane(p , Perp(tri.p[1]-tri.p[2])), sign)>0){d=DistPointEdge(point, tri.p[1], tri.p[2], &t); if(!type || d<dist){dist=d; type=UpdateTypeT(t, DIST_POINT1, DIST_POINT2, DIST_EDGE1);}}
  332. if(Xor(DistPointPlane(point, tri.p[2], Perp(tri.p[2]-tri.p[0])), sign)>0){d=DistPointEdge(point, tri.p[2], tri.p[0], &t); if(!type || d<dist){dist=d; type=UpdateTypeT(t, DIST_POINT2, DIST_POINT0, DIST_EDGE2);}}
  333. if(!type)
  334. {
  335. type=DIST_PLANE;
  336. dist=0;
  337. }
  338. if(_type)*_type=type; return dist;
  339. }
  340. Flt Dist(C Vec &point, C Tri &tri, DIST_TYPE *_type)
  341. {
  342. DIST_TYPE t, type=DIST_NONE;
  343. Flt d, dist=0;
  344. Vec p=point-tri.p[1]; if(DistPointPlane(p , Cross(tri.n, tri.p[0]-tri.p[1]))>0){d=DistPointEdge(point, tri.p[0], tri.p[1], &t); if(!type || d<dist){dist=d; type=UpdateTypeT(t, DIST_POINT0, DIST_POINT1, DIST_EDGE0);}}
  345. if(DistPointPlane(p , Cross(tri.n, tri.p[1]-tri.p[2]))>0){d=DistPointEdge(point, tri.p[1], tri.p[2], &t); if(!type || d<dist){dist=d; type=UpdateTypeT(t, DIST_POINT1, DIST_POINT2, DIST_EDGE1);}}
  346. if(DistPointPlane(point, tri.p[2], Cross(tri.n, tri.p[2]-tri.p[0]))>0){d=DistPointEdge(point, tri.p[2], tri.p[0], &t); if(!type || d<dist){dist=d; type=UpdateTypeT(t, DIST_POINT2, DIST_POINT0, DIST_EDGE2);}}
  347. if(!type)
  348. {
  349. type=DIST_PLANE;
  350. dist=Abs(DistPointPlane(point, tri));
  351. }
  352. if(_type)*_type=type; return dist;
  353. }
  354. Flt Dist(C Edge &edge, C Tri &tri)
  355. {
  356. // TODO: optimize
  357. if(Cuts(edge, tri))return 0;
  358. return Min(Min(Dist(edge , tri.edge0()),
  359. Dist(edge , tri.edge1()),
  360. Dist(edge , tri.edge2())),
  361. Dist(edge.p[0], tri ),
  362. Dist(edge.p[1], tri ));
  363. }
  364. Flt Dist(C Tri &a, C Tri &b)
  365. {
  366. // TODO: optimize
  367. return Min(Min(Dist(a.edge0(), b),
  368. Dist(a.edge1(), b),
  369. Dist(a.edge2(), b)),
  370. Min(Dist(b.edge0(), a),
  371. Dist(b.edge1(), a),
  372. Dist(b.edge2(), a)));
  373. }
  374. /******************************************************************************/
  375. Bool Cuts(C Vec &point, C Tri &tri, C Vec (&tri_cross)[3])
  376. {
  377. if(DistPointPlane(point, tri.p[0], tri_cross[0])>0)return false;
  378. if(DistPointPlane(point, tri.p[1], tri_cross[1])>0)return false;
  379. if(DistPointPlane(point, tri.p[2], tri_cross[2])>0)return false;
  380. return true;
  381. }
  382. /******************************************************************************/
  383. Bool Cuts(C Vec2 &point, C Tri2 &tri)
  384. {
  385. UInt sign=(tri.clockwise() ? 0 : SIGN_BIT); // counter-clockwise tris require changing sign
  386. Vec2 p=point-tri.p[1]; if(Xor(DistPointPlane(p , Perp(tri.p[0]-tri.p[1])), sign)>0)return false;
  387. if(Xor(DistPointPlane(p , Perp(tri.p[1]-tri.p[2])), sign)>0)return false;
  388. if(Xor(DistPointPlane(point, tri.p[2], Perp(tri.p[2]-tri.p[0])), sign)>0)return false;
  389. return true;
  390. }
  391. Bool Cuts(C VecD2 &point, C TriD2 &tri)
  392. {
  393. UInt sign=(tri.clockwise() ? 0 : SIGN_BIT); // counter-clockwise tris require changing sign
  394. VecD2 p=point-tri.p[1]; if(Xor(DistPointPlane(p , Perp(tri.p[0]-tri.p[1])), sign)>0)return false;
  395. if(Xor(DistPointPlane(p , Perp(tri.p[1]-tri.p[2])), sign)>0)return false;
  396. if(Xor(DistPointPlane(point, tri.p[2], Perp(tri.p[2]-tri.p[0])), sign)>0)return false;
  397. return true;
  398. }
  399. Bool Cuts(C Vec &point, C Tri &tri)
  400. {
  401. if(DistPointPlane(point, tri.p[0], Cross(tri.n, tri.p[0]-tri.p[1]))>0)return false;
  402. if(DistPointPlane(point, tri.p[1], Cross(tri.n, tri.p[1]-tri.p[2]))>0)return false;
  403. if(DistPointPlane(point, tri.p[2], Cross(tri.n, tri.p[2]-tri.p[0]))>0)return false;
  404. return true;
  405. }
  406. Bool Cuts(C VecD &point, C TriD &tri)
  407. {
  408. if(DistPointPlane(point, tri.p[0], Cross(tri.n, tri.p[0]-tri.p[1]))>0)return false;
  409. if(DistPointPlane(point, tri.p[1], Cross(tri.n, tri.p[1]-tri.p[2]))>0)return false;
  410. if(DistPointPlane(point, tri.p[2], Cross(tri.n, tri.p[2]-tri.p[0]))>0)return false;
  411. return true;
  412. }
  413. /******************************************************************************/
  414. Bool CutsEps(C Vec2 &point, C Tri2 &tri)
  415. {
  416. UInt sign=(tri.clockwise() ? 0 : SIGN_BIT); // counter-clockwise tris require changing sign
  417. Vec2 d10=!(tri.p[0]-tri.p[1]), p0=point-tri.p[0]; if(Xor(DistPointPlane(p0, Perp(d10)), sign)>EPS)return false;
  418. Vec2 d21=!(tri.p[1]-tri.p[2]), p1=point-tri.p[1]; if(Xor(DistPointPlane(p1, Perp(d21)), sign)>EPS)return false;
  419. Vec2 d02=!(tri.p[2]-tri.p[0]), p2=point-tri.p[2]; if(Xor(DistPointPlane(p2, Perp(d02)), sign)>EPS)return false;
  420. if( DistPointPlane(p0, !(d10-d02)) >EPS)return false;
  421. if( DistPointPlane(p1, !(d21-d10)) >EPS)return false;
  422. if( DistPointPlane(p2, !(d02-d21)) >EPS)return false;
  423. return true;
  424. }
  425. Bool CutsEps(C VecD2 &point, C TriD2 &tri)
  426. {
  427. UInt sign=(tri.clockwise() ? 0 : SIGN_BIT); // counter-clockwise tris require changing sign
  428. VecD2 d10=!(tri.p[0]-tri.p[1]), p0=point-tri.p[0]; if(Xor(DistPointPlane(p0, Perp(d10)), sign)>EPSD)return false;
  429. VecD2 d21=!(tri.p[1]-tri.p[2]), p1=point-tri.p[1]; if(Xor(DistPointPlane(p1, Perp(d21)), sign)>EPSD)return false;
  430. VecD2 d02=!(tri.p[2]-tri.p[0]), p2=point-tri.p[2]; if(Xor(DistPointPlane(p2, Perp(d02)), sign)>EPSD)return false;
  431. if( DistPointPlane(p0, !(d10-d02)) >EPSD)return false;
  432. if( DistPointPlane(p1, !(d21-d10)) >EPSD)return false;
  433. if( DistPointPlane(p2, !(d02-d21)) >EPSD)return false;
  434. return true;
  435. }
  436. Bool CutsEps(C Vec &point, C Tri &tri)
  437. {
  438. Vec d10=!(tri.p[0]-tri.p[1]); if(DistPointPlane(point, tri.p[0], Cross(tri.n, d10))>EPS)return false;
  439. Vec d21=!(tri.p[1]-tri.p[2]); if(DistPointPlane(point, tri.p[1], Cross(tri.n, d21))>EPS)return false;
  440. Vec d02=!(tri.p[2]-tri.p[0]); if(DistPointPlane(point, tri.p[2], Cross(tri.n, d02))>EPS)return false;
  441. if(DistPointPlane(point, tri.p[0], !(d10-d02))>EPS)return false;
  442. if(DistPointPlane(point, tri.p[1], !(d21-d10))>EPS)return false;
  443. if(DistPointPlane(point, tri.p[2], !(d02-d21))>EPS)return false;
  444. return true;
  445. }
  446. Bool CutsEps(C VecD &point, C TriD &tri)
  447. {
  448. VecD d10=!(tri.p[0]-tri.p[1]); if(DistPointPlane(point, tri.p[0], Cross(tri.n, d10))>EPSD)return false;
  449. VecD d21=!(tri.p[1]-tri.p[2]); if(DistPointPlane(point, tri.p[1], Cross(tri.n, d21))>EPSD)return false;
  450. VecD d02=!(tri.p[2]-tri.p[0]); if(DistPointPlane(point, tri.p[2], Cross(tri.n, d02))>EPSD)return false;
  451. if(DistPointPlane(point, tri.p[0], !(d10-d02))>EPSD)return false;
  452. if(DistPointPlane(point, tri.p[1], !(d21-d10))>EPSD)return false;
  453. if(DistPointPlane(point, tri.p[2], !(d02-d21))>EPSD)return false;
  454. return true;
  455. }
  456. /******************************************************************************/
  457. Bool Cuts(C Edge &edge, C Tri &tri)
  458. {
  459. Vec hitp;
  460. return Cuts(edge, tri.plane(), &hitp) && Cuts(hitp, tri);
  461. }
  462. /******************************************************************************/
  463. Int CutsTriPlane(C Tri &tri, C Plane &plane, Edge &edge)
  464. {
  465. Flt d0=Dist(tri.p[0], plane),
  466. d1=Dist(tri.p[1], plane),
  467. d2=Dist(tri.p[2], plane);
  468. Int s0=Sign(d0),
  469. s1=Sign(d1),
  470. s2=Sign(d2);
  471. if(!s0 && !s1 && !s2)return -1; // co-planar
  472. if( s0==s1 && s0==s2)return 0; // not cutting
  473. if(!s0 && !s1){edge.p[0]=tri.p[0]; edge.p[1]=tri.p[1]; return 2;}
  474. if(!s1 && !s2){edge.p[0]=tri.p[1]; edge.p[1]=tri.p[2]; return 2;}
  475. if(!s2 && !s0){edge.p[0]=tri.p[2]; edge.p[1]=tri.p[0]; return 2;}
  476. if(!s0 && s1==s2){edge.p[0]=tri.p[0]; return 1;}
  477. if(!s1 && s2==s0){edge.p[0]=tri.p[1]; return 1;}
  478. if(!s2 && s0==s1){edge.p[0]=tri.p[2]; return 1;}
  479. Int i=0;
  480. if(!s0){edge.p[0]=tri.p[0]; i++;}else
  481. if(!s1){edge.p[0]=tri.p[1]; i++;}else
  482. if(!s2){edge.p[0]=tri.p[2]; i++;}
  483. if(!(s0+s1))edge.p[i++]=PointOnPlane(tri.p[0], tri.p[1], d0, d1);
  484. if(!(s1+s2))edge.p[i++]=PointOnPlane(tri.p[1], tri.p[2], d1, d2);
  485. if(!(s2+s0))edge.p[i++]=PointOnPlane(tri.p[2], tri.p[0], d2, d0);
  486. return 2;
  487. }
  488. Int CutsTriPlaneEps(C Tri &tri, C Plane &plane, Edge &edge)
  489. {
  490. Flt d0=Dist(tri.p[0], plane),
  491. d1=Dist(tri.p[1], plane),
  492. d2=Dist(tri.p[2], plane);
  493. Int s0=SignEps(d0),
  494. s1=SignEps(d1),
  495. s2=SignEps(d2);
  496. if(!s0 && !s1 && !s2)return -1; // co-planar
  497. if( s0==s1 && s0==s2)return 0; // not cutting
  498. if(!s0 && !s1){edge.p[0]=tri.p[0]; edge.p[1]=tri.p[1]; return 2;}
  499. if(!s1 && !s2){edge.p[0]=tri.p[1]; edge.p[1]=tri.p[2]; return 2;}
  500. if(!s2 && !s0){edge.p[0]=tri.p[2]; edge.p[1]=tri.p[0]; return 2;}
  501. if(!s0 && s1==s2){edge.p[0]=tri.p[0]; return 1;}
  502. if(!s1 && s2==s0){edge.p[0]=tri.p[1]; return 1;}
  503. if(!s2 && s0==s1){edge.p[0]=tri.p[2]; return 1;}
  504. Int i=0;
  505. if(!s0){edge.p[0]=tri.p[0]; i++;}else
  506. if(!s1){edge.p[0]=tri.p[1]; i++;}else
  507. if(!s2){edge.p[0]=tri.p[2]; i++;}
  508. if(!(s0+s1))edge.p[i++]=PointOnPlane(tri.p[0], tri.p[1], d0, d1);
  509. if(!(s1+s2))edge.p[i++]=PointOnPlane(tri.p[1], tri.p[2], d1, d2);
  510. if(!(s2+s0))edge.p[i++]=PointOnPlane(tri.p[2], tri.p[0], d2, d0);
  511. return 2;
  512. }
  513. Int CutsTriPlane(C TriD &tri, C PlaneD &plane, EdgeD &edge)
  514. {
  515. Dbl d0=Dist(tri.p[0], plane),
  516. d1=Dist(tri.p[1], plane),
  517. d2=Dist(tri.p[2], plane);
  518. Int s0=Sign(d0),
  519. s1=Sign(d1),
  520. s2=Sign(d2);
  521. if(!s0 && !s1 && !s2)return -1; // co-planar
  522. if( s0==s1 && s0==s2)return 0; // not cutting
  523. if(!s0 && !s1){edge.p[0]=tri.p[0]; edge.p[1]=tri.p[1]; return 2;}
  524. if(!s1 && !s2){edge.p[0]=tri.p[1]; edge.p[1]=tri.p[2]; return 2;}
  525. if(!s2 && !s0){edge.p[0]=tri.p[2]; edge.p[1]=tri.p[0]; return 2;}
  526. if(!s0 && s1==s2){edge.p[0]=tri.p[0]; return 1;}
  527. if(!s1 && s2==s0){edge.p[0]=tri.p[1]; return 1;}
  528. if(!s2 && s0==s1){edge.p[0]=tri.p[2]; return 1;}
  529. Int i=0;
  530. if(!s0){edge.p[0]=tri.p[0]; i++;}else
  531. if(!s1){edge.p[0]=tri.p[1]; i++;}else
  532. if(!s2){edge.p[0]=tri.p[2]; i++;}
  533. if(!(s0+s1))edge.p[i++]=PointOnPlane(tri.p[0], tri.p[1], d0, d1);
  534. if(!(s1+s2))edge.p[i++]=PointOnPlane(tri.p[1], tri.p[2], d1, d2);
  535. if(!(s2+s0))edge.p[i++]=PointOnPlane(tri.p[2], tri.p[0], d2, d0);
  536. return 2;
  537. }
  538. Int CutsTriPlaneEps(C TriD &tri, C PlaneD &plane, EdgeD &edge)
  539. {
  540. Dbl d0=Dist(tri.p[0], plane),
  541. d1=Dist(tri.p[1], plane),
  542. d2=Dist(tri.p[2], plane);
  543. Int s0=SignEps(d0),
  544. s1=SignEps(d1),
  545. s2=SignEps(d2);
  546. if(!s0 && !s1 && !s2)return -1; // co-planar
  547. if( s0==s1 && s0==s2)return 0; // not cutting
  548. if(!s0 && !s1){edge.p[0]=tri.p[0]; edge.p[1]=tri.p[1]; return 2;}
  549. if(!s1 && !s2){edge.p[0]=tri.p[1]; edge.p[1]=tri.p[2]; return 2;}
  550. if(!s2 && !s0){edge.p[0]=tri.p[2]; edge.p[1]=tri.p[0]; return 2;}
  551. if(!s0 && s1==s2){edge.p[0]=tri.p[0]; return 1;}
  552. if(!s1 && s2==s0){edge.p[0]=tri.p[1]; return 1;}
  553. if(!s2 && s0==s1){edge.p[0]=tri.p[2]; return 1;}
  554. Int i=0;
  555. if(!s0){edge.p[0]=tri.p[0]; i++;}else
  556. if(!s1){edge.p[0]=tri.p[1]; i++;}else
  557. if(!s2){edge.p[0]=tri.p[2]; i++;}
  558. if(!(s0+s1))edge.p[i++]=PointOnPlane(tri.p[0], tri.p[1], d0, d1);
  559. if(!(s1+s2))edge.p[i++]=PointOnPlane(tri.p[1], tri.p[2], d1, d2);
  560. if(!(s2+s0))edge.p[i++]=PointOnPlane(tri.p[2], tri.p[0], d2, d0);
  561. return 2;
  562. }
  563. /******************************************************************************/
  564. Bool SweepPointTri(C Vec &point, C Vec &move, C Tri &tri, Flt *hit_frac, Vec *hit_pos, Bool two_sided)
  565. {
  566. Vec hitp;
  567. if(SweepPointPlane(point, move, tri.plane(), hit_frac, null, &hitp, two_sided))
  568. if(Cuts(hitp, tri))
  569. {
  570. if(hit_pos)*hit_pos=hitp;
  571. return true;
  572. }
  573. return false;
  574. }
  575. Bool SweepPointTriEps(C Vec &point, C Vec &move, C Tri &tri, Flt *hit_frac, Vec *hit_pos, Bool two_sided)
  576. {
  577. Vec hitp;
  578. if(SweepPointPlane(point, move, tri.plane(), hit_frac, null, &hitp, two_sided))
  579. if(CutsEps(hitp, tri))
  580. {
  581. if(hit_pos)*hit_pos=hitp;
  582. return true;
  583. }
  584. return false;
  585. }
  586. /******************************************************************************/
  587. Int Clip(Edge2 &edge, C Tri2 &tri)
  588. {
  589. UInt sign =(tri.clockwise() ? 0 : SIGN_BIT); // counter-clockwise tris require changing sign
  590. Byte edge_n[2]={0, 0};
  591. Vec2 tri_n[3]=
  592. {
  593. PerpN(tri.p[0]-tri.p[1]),
  594. PerpN(tri.p[1]-tri.p[2]),
  595. PerpN(tri.p[2]-tri.p[0]),
  596. };
  597. REPD(e, 3)
  598. {
  599. Edge2 cuts; if(Int c=CutsEdgeEdge(Edge2_I(tri.p[e], tri.p[(e+1)%3]), Edge2_I(edge.p[0], edge.p[1]), &cuts))
  600. {
  601. if(c==2)
  602. {
  603. if(++edge_n[0]>2
  604. || ++edge_n[1]>2)return 0;
  605. Int i=Closer(edge.p[0], cuts.p[0], cuts.p[1]);
  606. edge.p[0]=cuts.p[ i];
  607. edge.p[1]=cuts.p[!i];
  608. }else
  609. {
  610. Int dup;
  611. if(Equal(cuts.p[0], edge.p[0]))dup=0;else
  612. if(Equal(cuts.p[0], edge.p[1]))dup=1;else dup=-1;
  613. if(dup!=0 && Xor(DistPointPlane(edge.p[0], tri.p[e], tri_n[e]), sign)<0)dup=1;else
  614. if(dup!=1 && Xor(DistPointPlane(edge.p[1], tri.p[e], tri_n[e]), sign)<0)dup=0;else
  615. {
  616. edge.p[0]=cuts.p[0];
  617. return 1;
  618. }
  619. if(++edge_n[dup]>2)return 0;
  620. edge.p[dup]=cuts.p[0];
  621. }
  622. }
  623. }
  624. if(edge_n[0] || edge_n[1])return 2;
  625. return (Xor(DistPointPlane(edge.p[0], tri.p[0], tri_n[0]), sign)<0
  626. && Xor(DistPointPlane(edge.p[0], tri.p[1], tri_n[1]), sign)<0
  627. && Xor(DistPointPlane(edge.p[0], tri.p[2], tri_n[2]), sign)<0) ? 2 : 0;
  628. }
  629. Int Clip(EdgeD2 &edge, C TriD2 &tri)
  630. {
  631. UInt sign =(tri.clockwise() ? 0 : SIGN_BIT); // counter-clockwise tris require changing sign
  632. Byte edge_n[2]={0, 0};
  633. VecD2 tri_n[3]=
  634. {
  635. PerpN(tri.p[0]-tri.p[1]),
  636. PerpN(tri.p[1]-tri.p[2]),
  637. PerpN(tri.p[2]-tri.p[0]),
  638. };
  639. REPD(e, 3)
  640. {
  641. EdgeD2 cuts; if(Int c=CutsEdgeEdge(EdgeD2_I(tri.p[e], tri.p[(e+1)%3]), EdgeD2_I(edge.p[0], edge.p[1]), &cuts))
  642. {
  643. if(c==2)
  644. {
  645. if(++edge_n[0]>2
  646. || ++edge_n[1]>2)return 0;
  647. Int i=Closer(edge.p[0], cuts.p[0], cuts.p[1]);
  648. edge.p[0]=cuts.p[ i];
  649. edge.p[1]=cuts.p[!i];
  650. }else
  651. {
  652. Int dup;
  653. if(Equal(cuts.p[0], edge.p[0]))dup=0;else
  654. if(Equal(cuts.p[0], edge.p[1]))dup=1;else dup=-1;
  655. if(dup!=0 && Xor(DistPointPlane(edge.p[0], tri.p[e], tri_n[e]), sign)<0)dup=1;else
  656. if(dup!=1 && Xor(DistPointPlane(edge.p[1], tri.p[e], tri_n[e]), sign)<0)dup=0;else
  657. {
  658. edge.p[0]=cuts.p[0];
  659. return 1;
  660. }
  661. if(++edge_n[dup]>2)return 0;
  662. edge.p[dup]=cuts.p[0];
  663. }
  664. }
  665. }
  666. if(edge_n[0] || edge_n[1])return 2;
  667. return (Xor(DistPointPlane(edge.p[0], tri.p[0], tri_n[0]), sign)<0
  668. && Xor(DistPointPlane(edge.p[0], tri.p[1], tri_n[1]), sign)<0
  669. && Xor(DistPointPlane(edge.p[0], tri.p[2], tri_n[2]), sign)<0) ? 2 : 0;
  670. }
  671. /******************************************************************************/
  672. }
  673. /******************************************************************************/