NvRemoveTjunctions.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706
  1. /*
  2. NvRemoveTjunctions.cpp : A code snippet to remove tjunctions from a triangle mesh. This version is currently disabled as it appears to have a bug.
  3. */
  4. /*!
  5. **
  6. ** Copyright (c) 2009 by John W. Ratcliff mailto:[email protected]
  7. **
  8. ** Portions of this source has been released with the PhysXViewer application, as well as
  9. ** Rocket, CreateDynamics, ODF, and as a number of sample code snippets.
  10. **
  11. ** If you find this code useful or you are feeling particularily generous I would
  12. ** ask that you please go to http://www.amillionpixels.us and make a donation
  13. ** to Troy DeMolay.
  14. **
  15. ** DeMolay is a youth group for young men between the ages of 12 and 21.
  16. ** It teaches strong moral principles, as well as leadership skills and
  17. ** public speaking. The donations page uses the 'pay for pixels' paradigm
  18. ** where, in this case, a pixel is only a single penny. Donations can be
  19. ** made for as small as $4 or as high as a $100 block. Each person who donates
  20. ** will get a link to their own site as well as acknowledgement on the
  21. ** donations blog located here http://www.amillionpixels.blogspot.com/
  22. **
  23. ** If you wish to contact me you can use the following methods:
  24. **
  25. ** Skype ID: jratcliff63367
  26. ** Yahoo: jratcliff63367
  27. ** AOL: jratcliff1961
  28. ** email: [email protected]
  29. **
  30. **
  31. ** The MIT license:
  32. **
  33. ** Permission is hereby granted, free of charge, to any person obtaining a copy
  34. ** of this software and associated documentation files (the "Software"), to deal
  35. ** in the Software without restriction, including without limitation the rights
  36. ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  37. ** copies of the Software, and to permit persons to whom the Software is furnished
  38. ** to do so, subject to the following conditions:
  39. **
  40. ** The above copyright notice and this permission notice shall be included in all
  41. ** copies or substantial portions of the Software.
  42. ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  43. ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  44. ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  45. ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  46. ** WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  47. ** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  48. */
  49. #include <stdio.h>
  50. #include <stdlib.h>
  51. #include <string.h>
  52. #include <assert.h>
  53. #pragma warning(disable:4702)
  54. #pragma warning(disable:4127) //conditional expression is constant (because _HAS_EXCEPTIONS=0)
  55. #include <vector>
  56. #ifdef __APPLE__
  57. #include <ext/hash_map>
  58. #else
  59. #include <hash_map>
  60. #endif
  61. #include "NvUserMemAlloc.h"
  62. #include "NvHashMap.h"
  63. #include "NvRemoveTjunctions.h"
  64. #include "NvFloatMath.h"
  65. #pragma warning(disable:4189)
  66. using namespace CONVEX_DECOMPOSITION;
  67. namespace CONVEX_DECOMPOSITION
  68. {
  69. class AABB
  70. {
  71. public:
  72. NxF32 mMin[3];
  73. NxF32 mMax[3];
  74. };
  75. bool gDebug=false;
  76. NxU32 gCount=0;
  77. typedef CONVEX_DECOMPOSITION::Array< NxU32 > NxU32Vector;
  78. class Triangle
  79. {
  80. public:
  81. Triangle(void)
  82. {
  83. mPending = false;
  84. mSplit = false;
  85. mI1 = mI2 = mI3 = 0xFFFFFFFF;
  86. mId = 0;
  87. }
  88. Triangle(NxU32 i1,NxU32 i2,NxU32 i3,const float *vertices,NxU32 id)
  89. {
  90. mPending = false;
  91. init(i1,i2,i3,vertices,id);
  92. mSplit = false;
  93. }
  94. void init(NxU32 i1,NxU32 i2,NxU32 i3,const float *vertices,NxU32 id)
  95. {
  96. mSplit = false;
  97. mI1 = i1;
  98. mI2 = i2;
  99. mI3 = i3;
  100. mId = id;
  101. const float *p1 = &vertices[mI1*3];
  102. const float *p2 = &vertices[mI2*3];
  103. const float *p3 = &vertices[mI3*3];
  104. initMinMax(p1,p2,p3);
  105. }
  106. void initMinMax(const float *p1,const float *p2,const float *p3)
  107. {
  108. fm_copy3(p1,mBmin);
  109. fm_copy3(p1,mBmax);
  110. fm_minmax(p2,mBmin,mBmax);
  111. fm_minmax(p3,mBmin,mBmax);
  112. }
  113. void init(const NxU32 *idx,const float *vertices,NxU32 id)
  114. {
  115. mSplit = false;
  116. mI1 = idx[0];
  117. mI2 = idx[1];
  118. mI3 = idx[2];
  119. mId = id;
  120. const float *p1 = &vertices[mI1*3];
  121. const float *p2 = &vertices[mI2*3];
  122. const float *p3 = &vertices[mI3*3];
  123. initMinMax(p1,p2,p3);
  124. }
  125. bool intersects(const float *pos,const float *p1,const float *p2,float epsilon) const
  126. {
  127. bool ret = false;
  128. float sect[3];
  129. LineSegmentType type;
  130. float dist = fm_distancePointLineSegment(pos,p1,p2,sect,type,epsilon);
  131. if ( type == LS_MIDDLE && dist < epsilon )
  132. {
  133. ret = true;
  134. }
  135. return ret;
  136. }
  137. bool intersects(NxU32 i,const float *vertices,NxU32 &edge,float epsilon) const
  138. {
  139. bool ret = true;
  140. const float *pos = &vertices[i*3];
  141. const float *p1 = &vertices[mI1*3];
  142. const float *p2 = &vertices[mI2*3];
  143. const float *p3 = &vertices[mI3*3];
  144. if ( intersects(pos,p1,p2,epsilon) )
  145. {
  146. edge = 0;
  147. }
  148. else if ( intersects(pos,p2,p3,epsilon) )
  149. {
  150. edge = 1;
  151. }
  152. else if ( intersects(pos,p3,p1,epsilon) )
  153. {
  154. edge = 2;
  155. }
  156. else
  157. {
  158. ret = false;
  159. }
  160. return ret;
  161. }
  162. bool intersects(const Triangle *t,const float *vertices,NxU32 &intersection_index,NxU32 &edge,float epsilon)
  163. {
  164. bool ret = false;
  165. if ( fm_intersectAABB(mBmin,mBmax,t->mBmin,t->mBmax) ) // only if the AABB's of the two triangles intersect...
  166. {
  167. if ( t->intersects(mI1,vertices,edge,epsilon) )
  168. {
  169. intersection_index = mI1;
  170. ret = true;
  171. }
  172. if ( t->intersects(mI2,vertices,edge,epsilon) )
  173. {
  174. intersection_index = mI2;
  175. ret = true;
  176. }
  177. if ( t->intersects(mI3,vertices,edge,epsilon) )
  178. {
  179. intersection_index = mI3;
  180. ret = true;
  181. }
  182. }
  183. return ret;
  184. }
  185. bool mSplit:1;
  186. bool mPending:1;
  187. NxU32 mI1;
  188. NxU32 mI2;
  189. NxU32 mI3;
  190. NxU32 mId;
  191. float mBmin[3];
  192. float mBmax[3];
  193. };
  194. class RtEdge
  195. {
  196. public:
  197. RtEdge(void)
  198. {
  199. mNextEdge = 0;
  200. mTriangle = 0;
  201. mHash = 0;
  202. }
  203. NxU32 init(Triangle *t,NxU32 i1,NxU32 i2)
  204. {
  205. mTriangle = t;
  206. mNextEdge = 0;
  207. NX_ASSERT( i1 < 65536 );
  208. NX_ASSERT( i2 < 65536 );
  209. if ( i1 < i2 )
  210. {
  211. mHash = (i1<<16)|i2;
  212. }
  213. else
  214. {
  215. mHash = (i2<<16)|i1;
  216. }
  217. return mHash;
  218. }
  219. RtEdge *mNextEdge;
  220. Triangle *mTriangle;
  221. NxU32 mHash;
  222. };
  223. typedef CONVEX_DECOMPOSITION::Array< Triangle * > TriangleVector;
  224. typedef CONVEX_DECOMPOSITION::HashMap< NxU32, RtEdge * > EdgeMap;
  225. class MyRemoveTjunctions : public RemoveTjunctions
  226. {
  227. public:
  228. MyRemoveTjunctions(void)
  229. {
  230. mInputTriangles = 0;
  231. mEdges = 0;
  232. mVcount = 0;
  233. mVertices = 0;
  234. mEdgeCount = 0;
  235. }
  236. ~MyRemoveTjunctions(void)
  237. {
  238. release();
  239. }
  240. virtual NxU32 removeTjunctions(RemoveTjunctionsDesc &desc)
  241. {
  242. NxU32 ret = 0;
  243. mEpsilon = desc.mEpsilon;
  244. size_t TcountOut;
  245. desc.mIndicesOut = removeTjunctions(desc.mVcount, desc.mVertices, desc.mTcount, desc.mIndices, TcountOut, desc.mIds);
  246. #ifdef WIN32
  247. # pragma warning(push)
  248. # pragma warning(disable:4267)
  249. #endif
  250. NX_ASSERT( TcountOut < UINT_MAX );
  251. desc.mTcountOut = TcountOut;
  252. #ifdef WIN32
  253. # pragma warning(pop)
  254. #endif
  255. if ( !mIds.empty() )
  256. {
  257. desc.mIdsOut = &mIds[0];
  258. }
  259. ret = desc.mTcountOut;
  260. bool check = ret != desc.mTcount;
  261. #if 0
  262. while ( check )
  263. {
  264. NxU32 tcount = ret;
  265. NxU32 *indices = new NxU32[tcount*3];
  266. NxU32 *ids = new NxU32[tcount];
  267. memcpy(indices,desc.mIndicesOut,sizeof(NxU32)*ret*3);
  268. memcpy(ids,desc.mIdsOut,sizeof(NxU32)*ret);
  269. desc.mIndicesOut = removeTjunctions(desc.mVcount, desc.mVertices, tcount, indices, desc.mTcountOut, ids );
  270. if ( !mIds.empty() )
  271. {
  272. desc.mIdsOut = &mIds[0];
  273. }
  274. ret = desc.mTcountOut;
  275. delete []indices;
  276. delete []ids;
  277. check = ret != tcount;
  278. }
  279. #endif
  280. return ret;
  281. }
  282. RtEdge * addEdge(Triangle *t,RtEdge *e,NxU32 i1,NxU32 i2)
  283. {
  284. NxU32 hash = e->init(t,i1,i2);
  285. const EdgeMap::Entry *found = mEdgeMap.find(hash);
  286. if ( found == NULL )
  287. {
  288. mEdgeMap[hash] = e;
  289. }
  290. else
  291. {
  292. RtEdge *old_edge = (*found).second;
  293. e->mNextEdge = old_edge;
  294. mEdgeMap.erase(hash);
  295. mEdgeMap[hash] = e;
  296. }
  297. e++;
  298. mEdgeCount++;
  299. return e;
  300. }
  301. RtEdge * init(Triangle *t,const NxU32 *indices,const float *vertices,RtEdge *e,NxU32 id)
  302. {
  303. t->init(indices,vertices,id);
  304. e = addEdge(t,e,t->mI1,t->mI2);
  305. e = addEdge(t,e,t->mI2,t->mI3);
  306. e = addEdge(t,e,t->mI3,t->mI1);
  307. return e;
  308. }
  309. void release(void)
  310. {
  311. mIds.clear();
  312. mEdgeMap.clear();
  313. mIndices.clear();
  314. mSplit.clear();
  315. delete []mInputTriangles;
  316. delete []mEdges;
  317. mInputTriangles = 0;
  318. mEdges = 0;
  319. mVcount = 0;
  320. mVertices = 0;
  321. mEdgeCount = 0;
  322. }
  323. virtual NxU32 * removeTjunctions(NxU32 vcount,
  324. const float *vertices,
  325. size_t tcount,
  326. const NxU32 *indices,
  327. size_t &tcount_out,
  328. const NxU32 * ids)
  329. {
  330. NxU32 *ret = 0;
  331. release();
  332. mVcount = vcount;
  333. mVertices = vertices;
  334. mTcount = (NxU32)tcount;
  335. tcount_out = 0;
  336. mTcount = (NxU32)tcount;
  337. mMaxTcount = (NxU32)tcount*2;
  338. mInputTriangles = new Triangle[mMaxTcount];
  339. Triangle *t = mInputTriangles;
  340. mEdges = new RtEdge[mMaxTcount*3];
  341. mEdgeCount = 0;
  342. NxU32 id = 0;
  343. RtEdge *e = mEdges;
  344. for (NxU32 i=0; i<tcount; i++)
  345. {
  346. if ( ids ) id = *ids++;
  347. e =init(t,indices,vertices,e,id);
  348. indices+=3;
  349. t++;
  350. }
  351. {
  352. TriangleVector test;
  353. for (EdgeMap::Iterator i = mEdgeMap.getIterator(); !i.done(); ++i)
  354. {
  355. RtEdge *e = (*i).second;
  356. if ( e->mNextEdge == 0 ) // open edge!
  357. {
  358. Triangle *t = e->mTriangle;
  359. if ( !t->mPending )
  360. {
  361. test.pushBack(t);
  362. t->mPending = true;
  363. }
  364. }
  365. }
  366. if ( !test.empty() )
  367. {
  368. TriangleVector::Iterator i;
  369. for (i=test.begin(); i!=test.end(); ++i)
  370. {
  371. Triangle *t = (*i);
  372. locateIntersection(t);
  373. }
  374. }
  375. }
  376. while ( !mSplit.empty() )
  377. {
  378. TriangleVector scan = mSplit;
  379. mSplit.clear();
  380. TriangleVector::Iterator i;
  381. for (i=scan.begin(); i!=scan.end(); ++i)
  382. {
  383. Triangle *t = (*i);
  384. locateIntersection(t);
  385. }
  386. }
  387. mIndices.clear();
  388. mIds.clear();
  389. t = mInputTriangles;
  390. for (NxU32 i=0; i<mTcount; i++)
  391. {
  392. mIndices.pushBack(t->mI1);
  393. mIndices.pushBack(t->mI2);
  394. mIndices.pushBack(t->mI3);
  395. mIds.pushBack(t->mId);
  396. t++;
  397. }
  398. mEdgeMap.clear();
  399. delete []mEdges;
  400. mEdges = 0;
  401. delete []mInputTriangles;
  402. mInputTriangles = 0;
  403. tcount_out = mIndices.size()/3;
  404. ret = tcount_out ? &mIndices[0] : 0;
  405. #ifdef _DEBUG
  406. if ( ret )
  407. {
  408. const NxU32 *scan = ret;
  409. for (NxU32 i=0; i<tcount_out; i++)
  410. {
  411. NxU32 i1 = scan[0];
  412. NxU32 i2 = scan[1];
  413. NxU32 i3 = scan[2];
  414. assert( i1 != i2 && i1 != i3 && i2 != i3 );
  415. scan+=3;
  416. }
  417. }
  418. #endif
  419. return ret;
  420. }
  421. Triangle * locateIntersection(Triangle *scan,Triangle *t)
  422. {
  423. Triangle *ret = 0;
  424. NxU32 t1 = (NxU32)(scan-mInputTriangles);
  425. NxU32 t2 = (NxU32)(t-mInputTriangles);
  426. NX_ASSERT( t1 < mTcount );
  427. NX_ASSERT( t2 < mTcount );
  428. NX_ASSERT( scan->mI1 < mVcount );
  429. NX_ASSERT( scan->mI2 < mVcount );
  430. NX_ASSERT( scan->mI3 < mVcount );
  431. NX_ASSERT( t->mI1 < mVcount );
  432. NX_ASSERT( t->mI2 < mVcount );
  433. NX_ASSERT( t->mI3 < mVcount );
  434. NxU32 intersection_index;
  435. NxU32 edge;
  436. if ( scan != t && scan->intersects(t,mVertices,intersection_index,edge,mEpsilon) )
  437. {
  438. if ( t->mI1 == intersection_index || t->mI2 == intersection_index || t->mI3 == intersection_index )
  439. {
  440. }
  441. else
  442. {
  443. // here is where it intersects!
  444. NxU32 i1,i2,i3;
  445. NxU32 j1,j2,j3;
  446. NxU32 id = t->mId;
  447. switch ( edge )
  448. {
  449. case 0:
  450. i1 = t->mI1;
  451. i2 = intersection_index;
  452. i3 = t->mI3;
  453. j1 = intersection_index;
  454. j2 = t->mI2;
  455. j3 = t->mI3;
  456. break;
  457. case 1:
  458. i1 = t->mI2;
  459. i2 = intersection_index;
  460. i3 = t->mI1;
  461. j1 = intersection_index;
  462. j2 = t->mI3;
  463. j3 = t->mI1;
  464. break;
  465. case 2:
  466. i1 = t->mI3;
  467. i2 = intersection_index;
  468. i3 = t->mI2;
  469. j1 = intersection_index;
  470. j2 = t->mI1;
  471. j3 = t->mI2;
  472. break;
  473. default:
  474. NX_ASSERT(0);
  475. i1 = i2 = i3 = 0;
  476. j1 = j2 = j3 = 0;
  477. break;
  478. }
  479. if ( mTcount < mMaxTcount )
  480. {
  481. t->init(i1,i2,i3,mVertices,id);
  482. Triangle *newt = &mInputTriangles[mTcount];
  483. newt->init(j1,j2,j3,mVertices,id);
  484. mTcount++;
  485. t->mSplit = true;
  486. newt->mSplit = true;
  487. mSplit.pushBack(t);
  488. mSplit.pushBack(newt);
  489. ret = scan;
  490. }
  491. }
  492. }
  493. return ret;
  494. }
  495. Triangle * testIntersection(Triangle *scan,Triangle *t)
  496. {
  497. Triangle *ret = 0;
  498. NxU32 t1 = (NxU32)(scan-mInputTriangles);
  499. NxU32 t2 = (NxU32)(t-mInputTriangles);
  500. NX_ASSERT( t1 < mTcount );
  501. NX_ASSERT( t2 < mTcount );
  502. NX_ASSERT( scan->mI1 < mVcount );
  503. NX_ASSERT( scan->mI2 < mVcount );
  504. NX_ASSERT( scan->mI3 < mVcount );
  505. NX_ASSERT( t->mI1 < mVcount );
  506. NX_ASSERT( t->mI2 < mVcount );
  507. NX_ASSERT( t->mI3 < mVcount );
  508. NxU32 intersection_index;
  509. NxU32 edge;
  510. assert( scan != t );
  511. if ( scan->intersects(t,mVertices,intersection_index,edge,mEpsilon) )
  512. {
  513. // here is where it intersects!
  514. NxU32 i1,i2,i3;
  515. NxU32 j1,j2,j3;
  516. NxU32 id = t->mId;
  517. switch ( edge )
  518. {
  519. case 0:
  520. i1 = t->mI1;
  521. i2 = intersection_index;
  522. i3 = t->mI3;
  523. j1 = intersection_index;
  524. j2 = t->mI2;
  525. j3 = t->mI3;
  526. break;
  527. case 1:
  528. i1 = t->mI2;
  529. i2 = intersection_index;
  530. i3 = t->mI1;
  531. j1 = intersection_index;
  532. j2 = t->mI3;
  533. j3 = t->mI1;
  534. break;
  535. case 2:
  536. i1 = t->mI3;
  537. i2 = intersection_index;
  538. i3 = t->mI2;
  539. j1 = intersection_index;
  540. j2 = t->mI1;
  541. j3 = t->mI2;
  542. break;
  543. default:
  544. NX_ASSERT(0);
  545. i1 = i2 = i3 = 0;
  546. j1 = j2 = j3 = 0;
  547. break;
  548. }
  549. if ( mTcount < mMaxTcount )
  550. {
  551. t->init(i1,i2,i3,mVertices,id);
  552. Triangle *newt = &mInputTriangles[mTcount];
  553. newt->init(j1,j2,j3,mVertices,id);
  554. mTcount++;
  555. t->mSplit = true;
  556. newt->mSplit = true;
  557. mSplit.pushBack(t);
  558. mSplit.pushBack(newt);
  559. ret = scan;
  560. }
  561. }
  562. return ret;
  563. }
  564. Triangle * locateIntersection(Triangle *t)
  565. {
  566. Triangle *ret = 0;
  567. Triangle *scan = mInputTriangles;
  568. for (NxU32 i=0; i<mTcount; i++)
  569. {
  570. ret = locateIntersection(scan,t);
  571. if ( ret )
  572. break;
  573. scan++;
  574. }
  575. return ret;
  576. }
  577. Triangle *mInputTriangles;
  578. NxU32 mVcount;
  579. NxU32 mMaxTcount;
  580. NxU32 mTcount;
  581. const float *mVertices;
  582. NxU32Vector mIndices;
  583. NxU32Vector mIds;
  584. TriangleVector mSplit;
  585. NxU32 mEdgeCount;
  586. RtEdge *mEdges;
  587. EdgeMap mEdgeMap;
  588. NxF32 mEpsilon;
  589. };
  590. RemoveTjunctions * createRemoveTjunctions(void)
  591. {
  592. MyRemoveTjunctions *m = new MyRemoveTjunctions;
  593. return static_cast< RemoveTjunctions *>(m);
  594. }
  595. void releaseRemoveTjunctions(RemoveTjunctions *tj)
  596. {
  597. MyRemoveTjunctions *m = static_cast< MyRemoveTjunctions *>(tj);
  598. delete m;
  599. }
  600. }; // end of namespace