decomposePoly.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580
  1. #include "math/util/decomposePoly.h"
  2. // twoIndices Methods
  3. twoIndices::twoIndices()
  4. {
  5. i1 = i2 = 0;
  6. }
  7. twoIndices::twoIndices(U8 a, U8 b)
  8. {
  9. i1 = a;
  10. i2 = b;
  11. }
  12. // decompTri Methods
  13. decompTri::decompTri()
  14. {
  15. mVertIdx[0] = 0;
  16. mVertIdx[1] = 0;
  17. mVertIdx[2] = 0;
  18. }
  19. void decompTri::orderVerts()
  20. {
  21. // Bubble sort, smallest to largest
  22. U8 temp;
  23. for (U8 i = 2; i > 0; i--)
  24. {
  25. for (U8 j = 0; j < i; j++)
  26. {
  27. if (mVertIdx[j] > mVertIdx[j + 1])
  28. {
  29. temp = mVertIdx[j];
  30. mVertIdx[j] = mVertIdx[j + 1];
  31. mVertIdx[j + 1] = temp;
  32. }
  33. }
  34. }
  35. }
  36. void decompTri::setVert(U8 val, U8 idx)
  37. {
  38. if(idx < 3)
  39. mVertIdx[idx] = val;
  40. }
  41. U8 decompTri::getVert(U8 idx)
  42. {
  43. if(idx < 3)
  44. return mVertIdx[idx];
  45. return mVertIdx[2];
  46. }
  47. twoIndices decompTri::getOtherVerts(U8 idx)
  48. {
  49. if(idx == mVertIdx[0])
  50. return twoIndices(mVertIdx[1], mVertIdx[2]);
  51. if(idx == mVertIdx[1])
  52. return twoIndices(mVertIdx[0], mVertIdx[2]);
  53. if(idx == mVertIdx[2])
  54. return twoIndices(mVertIdx[0], mVertIdx[1]);
  55. return twoIndices(0,0);
  56. }
  57. // decompPoly Methods
  58. void decompPoly::addVert(Point3F &newVert)
  59. {
  60. bool found = false;
  61. for(U8 i = 0; i < mVertList.size(); i++)
  62. {
  63. if(newVert == mVertList[i])
  64. found = true;
  65. }
  66. if(!found)
  67. mVertList.push_back(newVert);
  68. }
  69. void decompPoly::initEdgeList()
  70. {
  71. mEdgeList.clear();
  72. S32 next = 0;
  73. for(S32 i = 0; i < mVertList.size(); i++)
  74. {
  75. if(i == mVertList.size()-1)
  76. next = 0;
  77. else
  78. next = i+1;
  79. mEdgeList.push_back(twoIndices(i, next));
  80. }
  81. }
  82. bool decompPoly::sameSide(Point3F &p1, Point3F &p2, Point3F &l1, Point3F &l2)
  83. {
  84. return ((p1.x-l1.x)*(l2.y-l1.y)-(l2.x-l1.x)*(p1.y-l1.y))*((p2.x-l1.x)*(l2.y-l1.y)-(l2.x-l1.x)*(p2.y-l1.y)) > 0;
  85. }
  86. bool decompPoly::isInside(decompTri &tri, U8 vertIdx)
  87. {
  88. Point3F a(mVertList[tri.getVert(0)]);
  89. Point3F b(mVertList[tri.getVert(1)]);
  90. Point3F c(mVertList[tri.getVert(2)]);
  91. Point3F p(mVertList[vertIdx]);
  92. return (sameSide(p,a,b,c) && sameSide(p,b,a,c) && sameSide(p,c,a,b));
  93. }
  94. U8 decompPoly::leftmost()
  95. {
  96. F32 xMin = 9999999.f;
  97. U8 idx = 0;
  98. for(U8 i = 0; i < mVertList.size(); i++)
  99. {
  100. if(mVertList[i].x < xMin && isVertInEdgeList(i))
  101. {
  102. xMin = mVertList[i].x;
  103. idx = i;
  104. }
  105. }
  106. return idx;
  107. }
  108. U8 decompPoly::rightmost()
  109. {
  110. F32 xMax = -9999999.f;
  111. U8 idx = 0;
  112. for(U8 i = 0; i < mVertList.size(); i++)
  113. {
  114. if(mVertList[i].x > xMax && isVertInEdgeList(i))
  115. {
  116. xMax = mVertList[i].x;
  117. idx = i;
  118. }
  119. }
  120. return idx;
  121. }
  122. U8 decompPoly::uppermost()
  123. {
  124. F32 yMax = -9999999.f;
  125. U8 idx = 0;
  126. for(U8 i = 0; i < mVertList.size(); i++)
  127. {
  128. if(mVertList[i].y > yMax && isVertInEdgeList(i))
  129. {
  130. yMax = mVertList[i].y;
  131. idx = i;
  132. }
  133. }
  134. return idx;
  135. }
  136. U8 decompPoly::lowermost()
  137. {
  138. F32 yMin = 9999999.f;
  139. U8 idx = 0;
  140. for(U8 i = 0; i < mVertList.size(); i++)
  141. {
  142. if(mVertList[i].y < yMin && isVertInEdgeList(i))
  143. {
  144. yMin = mVertList[i].y;
  145. idx = i;
  146. }
  147. }
  148. return idx;
  149. }
  150. twoIndices decompPoly::findEdges(U8 vertIdx, bool &notUnique)
  151. {
  152. U8 found = 0;
  153. U8 edgeIdx[2];
  154. for(U8 i = 0; i < mEdgeList.size(); i++)
  155. {
  156. if(mEdgeList[i].i1 == vertIdx || mEdgeList[i].i2 == vertIdx)
  157. {
  158. edgeIdx[found++] = i;
  159. }
  160. }
  161. notUnique = found > 2;
  162. return twoIndices(edgeIdx[0], edgeIdx[1]);
  163. }
  164. decompTri decompPoly::formTriFromEdges(U8 idx1, U8 idx2)
  165. {
  166. decompTri tri;
  167. tri.setVert(mEdgeList[idx1].i1, 0);
  168. tri.setVert(mEdgeList[idx1].i2, 1);
  169. if(mEdgeList[idx2].i1 == tri.getVert(0) || mEdgeList[idx2].i1 == tri.getVert(1))
  170. {
  171. tri.setVert(mEdgeList[idx2].i2, 2);
  172. }
  173. else
  174. {
  175. tri.setVert(mEdgeList[idx2].i1, 2);
  176. }
  177. return tri;
  178. }
  179. twoIndices decompPoly::leftmostInsideVerts(U8 idx1, U8 idx2)
  180. {
  181. F32 xMin = 9999999.f;
  182. S32 left[] = {-1, -1};
  183. for(U8 i = 0; i < 2; i++)
  184. {
  185. for(U8 j = 0; j < mInsideVerts.size(); j++)
  186. {
  187. if(mVertList[mInsideVerts[j]].x < xMin && mInsideVerts[j] != left[0])
  188. {
  189. xMin = mVertList[mInsideVerts[j]].x;
  190. left[i] = mInsideVerts[j];
  191. }
  192. }
  193. if(mVertList[idx1].x < xMin && idx1 != left[0])
  194. {
  195. xMin = mVertList[idx1].x;
  196. left[i] = idx1;
  197. }
  198. if(mVertList[idx2].x < xMin && idx2 != left[0])
  199. {
  200. xMin = mVertList[idx2].x;
  201. left[i] = idx2;
  202. }
  203. xMin = 9999999.f;
  204. }
  205. return twoIndices(left[0], left[1]);
  206. }
  207. twoIndices decompPoly::rightmostInsideVerts(U8 idx1, U8 idx2)
  208. {
  209. F32 xMax = -9999999.f;
  210. S32 right[] = {-1, -1};
  211. for(U8 i = 0; i < 2; i++)
  212. {
  213. for(U8 j = 0; j < mInsideVerts.size(); j++)
  214. {
  215. if(mVertList[mInsideVerts[j]].x > xMax && mInsideVerts[j] != right[0])
  216. {
  217. xMax = mVertList[mInsideVerts[j]].x;
  218. right[i] = mInsideVerts[j];
  219. }
  220. }
  221. if(mVertList[idx1].x > xMax && idx1 != right[0])
  222. {
  223. xMax = mVertList[idx1].x;
  224. right[i] = idx1;
  225. }
  226. if(mVertList[idx2].x > xMax && idx2 != right[0])
  227. {
  228. xMax = mVertList[idx2].x;
  229. right[i] = idx2;
  230. }
  231. xMax = -9999999.f;
  232. }
  233. return twoIndices(right[0], right[1]);
  234. }
  235. twoIndices decompPoly::uppermostInsideVerts(U8 idx1, U8 idx2)
  236. {
  237. F32 yMax = -9999999.f;
  238. S32 up[] = {-1, -1};
  239. for(U8 i = 0; i < 2; i++)
  240. {
  241. for(U8 j = 0; j < mInsideVerts.size(); j++)
  242. {
  243. if(mVertList[mInsideVerts[j]].y > yMax && mInsideVerts[j] != up[0])
  244. {
  245. yMax = mVertList[mInsideVerts[j]].y;
  246. up[i] = mInsideVerts[j];
  247. }
  248. }
  249. if(mVertList[idx1].y > yMax && idx1 != up[0])
  250. {
  251. yMax = mVertList[idx1].y;
  252. up[i] = idx1;
  253. }
  254. if(mVertList[idx2].y > yMax && idx2 != up[0])
  255. {
  256. yMax = mVertList[idx2].y;
  257. up[i] = idx2;
  258. }
  259. yMax = -9999999.f;
  260. }
  261. return twoIndices(up[0], up[1]);
  262. }
  263. twoIndices decompPoly::lowermostInsideVerts(U8 idx1, U8 idx2)
  264. {
  265. F32 yMin = 9999999.f;
  266. S32 down[] = {-1, -1};
  267. for(U8 i = 0; i < 2; i++)
  268. {
  269. for(U8 j = 0; j < mInsideVerts.size(); j++)
  270. {
  271. if(mVertList[mInsideVerts[j]].y < yMin && mInsideVerts[j] != down[0])
  272. {
  273. yMin = mVertList[mInsideVerts[j]].y;
  274. down[i] = mInsideVerts[j];
  275. }
  276. }
  277. if(mVertList[idx1].y < yMin && idx1 != down[0])
  278. {
  279. yMin = mVertList[idx1].y;
  280. down[i] = idx1;
  281. }
  282. if(mVertList[idx2].y < yMin && idx2 != down[0])
  283. {
  284. yMin = mVertList[idx2].y;
  285. down[i] = idx2;
  286. }
  287. yMin = 9999999.f;
  288. }
  289. return twoIndices(down[0], down[1]);
  290. }
  291. void decompPoly::findPointsInside()
  292. {
  293. mInsideVerts.clear();
  294. for(U8 i = 0; i < mVertList.size(); i++)
  295. {
  296. if(i != mTestTri.getVert(0) && i != mTestTri.getVert(1) && i != mTestTri.getVert(2))
  297. {
  298. if(isInside(mTestTri, i))
  299. {
  300. mInsideVerts.push_back(i);
  301. }
  302. }
  303. }
  304. }
  305. void decompPoly::addRemoveEdge(U8 idx1, U8 idx2)
  306. {
  307. twoIndices edge1(idx1, idx2);
  308. if(!mEdgeList.remove(edge1))
  309. mEdgeList.push_back(edge1);
  310. }
  311. void decompPoly::newPoly()
  312. {
  313. mVertList.clear();
  314. mEdgeList.clear();
  315. mInsideVerts.clear();
  316. mTris.clear();
  317. }
  318. bool decompPoly::isVertInEdgeList(U8 idx)
  319. {
  320. for(U8 i = 0; i < mEdgeList.size(); i++)
  321. {
  322. if(mEdgeList[i].i1 == idx || mEdgeList[i].i2 == idx)
  323. return true;
  324. }
  325. return false;
  326. }
  327. Point3F decompPoly::getVert(U8 idx)
  328. {
  329. if(idx < mVertList.size())
  330. return mVertList[idx];
  331. return Point3F(0.0f, 0.0f, 0.0f);
  332. }
  333. U8 decompPoly::getTriIdx(U32 tri, U8 idx)
  334. {
  335. if(tri < mTris.size() && idx < 3)
  336. return mTris[tri].getVert(idx);
  337. return 0;
  338. }
  339. bool decompPoly::checkEdgeLength(F32 len)
  340. {
  341. Point3F p1, p2;
  342. for(U8 i = 0; i < mEdgeList.size(); i++)
  343. {
  344. p1 = mVertList[mEdgeList[i].i1];
  345. p2 = mVertList[mEdgeList[i].i2];
  346. p1 = p2 - p1;
  347. if(p1.len() < len)
  348. return false;
  349. }
  350. return true;
  351. }
  352. //---------------------------------------------------
  353. // Concave polygon decomposition into triangles
  354. //
  355. // Based upon this resource:
  356. // http://www.siggraph.org/education/materials/HyperGraph/scanline/outprims/polygon1.htm
  357. //
  358. // 1. Find leftmost vertex in polygon (smallest value along x-axis).
  359. // 2. Find the two edges adjacent to this vertex.
  360. // 3. Form a test tri by connecting the open side of these two edges.
  361. // 4. See if any of the vertices in the poly, besides the ones that form the test tri, are inside the
  362. // test tri.
  363. // 5. If there are verts inside, find the 3 leftmost of the inside verts and the test tri verts, form
  364. // a new test tri from these verts, and repeat from step 4. When no verts are inside, continue.
  365. // 6. Save test tri as a valid triangle.
  366. // 7. Remove the edges that the test tri and poly share, and add the new edges from the test tri to
  367. // the poly to form a new closed poly with the test tri subtracted out.
  368. //
  369. // Note: our polygon can contain no more than 255 verts. Complex polygons can create situations where
  370. // a vertex has more than 2 adjacent edges, causing step 2 to fail. This method improves on the resource
  371. // listed above by not limiting the decomposition to the leftmost side only. If step 2 fails, the
  372. // algorithm also tries to decompose the polygon from the top, right, and bottom until one succeeds or
  373. // they all fail. If they all fail, the polygon is too complex to be decomposed with this method.
  374. bool decompPoly::decompose()
  375. {
  376. // Must have at least 3 verts to form a poly
  377. if(mVertList.size() < 3)
  378. return false;
  379. // Clear out any previously stored tris
  380. mTris.clear();
  381. // Initialize the edge list with the default edges
  382. initEdgeList();
  383. twoIndices otherVerts, outerVerts2;
  384. U32 counter = 0;
  385. U8 uniqueVertAttempt = 0;
  386. U8 formTriAttempt = 0;
  387. bool notUnique = false;
  388. // The main decomposition loop
  389. while(mEdgeList.size() > 3)
  390. {
  391. // Find outermost vert in poly, LMV
  392. U8 outerVertIdx;
  393. switch(uniqueVertAttempt)
  394. {
  395. case 0: outerVertIdx = leftmost(); break;
  396. case 1: outerVertIdx = rightmost(); break;
  397. case 2: outerVertIdx = uppermost(); break;
  398. case 3: outerVertIdx = uppermost(); break;
  399. default: outerVertIdx = leftmost();
  400. }
  401. // Find edges that share LMV
  402. twoIndices edgesIdx = findEdges(outerVertIdx, notUnique);
  403. // If vert shares more than two edges, try decomposing from different direction
  404. if(notUnique)
  405. {
  406. if(uniqueVertAttempt < 4)
  407. {
  408. uniqueVertAttempt++;
  409. continue;
  410. }
  411. else
  412. {
  413. newPoly();
  414. return false;
  415. }
  416. }
  417. // Sanity check
  418. if(edgesIdx.i1 >= mEdgeList.size() || edgesIdx.i2 >= mEdgeList.size())
  419. {
  420. newPoly();
  421. return false;
  422. }
  423. // Form the test tri from these 2 edges
  424. mTestTri = formTriFromEdges(edgesIdx.i1, edgesIdx.i2);
  425. // See if there are any other poly verts inside the test tri
  426. findPointsInside();
  427. // If there are verts inside, repeat procedure until there are none
  428. while(mInsideVerts.size() > 0 && formTriAttempt++ < mVertList.size())
  429. {
  430. // Get the two verts of the test tri that are not the LMV
  431. otherVerts = mTestTri.getOtherVerts(outerVertIdx);
  432. // Get the 2 outermost verts of the inside and test tri verts (excluding LMV)
  433. switch(uniqueVertAttempt)
  434. {
  435. case 0: outerVerts2 = leftmostInsideVerts(otherVerts.i1, otherVerts.i2); break;
  436. case 1: outerVerts2 = rightmostInsideVerts(otherVerts.i1, otherVerts.i2); break;
  437. case 2: outerVerts2 = uppermostInsideVerts(otherVerts.i1, otherVerts.i2); break;
  438. case 3: outerVerts2 = uppermostInsideVerts(otherVerts.i1, otherVerts.i2); break;
  439. default: outerVerts2 = leftmostInsideVerts(otherVerts.i1, otherVerts.i2);
  440. }
  441. // Form a new test tri from LMV, and the 2 new leftmost verts above
  442. mTestTri.setVert(outerVerts2.i1, 0);
  443. mTestTri.setVert(outerVertIdx, 1);
  444. mTestTri.setVert(outerVerts2.i2, 2);
  445. // See if there are verts inside this new test tri
  446. findPointsInside();
  447. }
  448. // We have found a valid tri
  449. mTris.push_back(mTestTri);
  450. // Remove edges common to test tri and poly... add unique edges from test tri to poly
  451. addRemoveEdge(mTestTri.getVert(0), mTestTri.getVert(1));
  452. addRemoveEdge(mTestTri.getVert(1), mTestTri.getVert(2));
  453. addRemoveEdge(mTestTri.getVert(0), mTestTri.getVert(2));
  454. // This should never take 255 iterations... we must be stuck in an infinite loop
  455. if(counter++ > 255)
  456. {
  457. newPoly();
  458. return false;
  459. }
  460. // Reset attempts
  461. formTriAttempt = 0;
  462. uniqueVertAttempt = 0;
  463. }
  464. // The last tri
  465. mTris.push_back(formTriFromEdges(0,1));
  466. // The verts need to be ordered to draw correctly
  467. for(U8 i = 0; i < mTris.size(); i++)
  468. {
  469. mTris[i].orderVerts();
  470. }
  471. return true;
  472. }