optimizedPolyList.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "math/mMath.h"
  23. #include "core/color.h"
  24. #include "console/console.h"
  25. #include "collision/optimizedPolyList.h"
  26. #include "materials/baseMatInstance.h"
  27. #include "materials/materialDefinition.h"
  28. //----------------------------------------------------------------------------
  29. OptimizedPolyList::OptimizedPolyList()
  30. {
  31. VECTOR_SET_ASSOCIATION(mPoints);
  32. VECTOR_SET_ASSOCIATION(mNormals);
  33. VECTOR_SET_ASSOCIATION(mUV0s);
  34. VECTOR_SET_ASSOCIATION(mUV1s);
  35. VECTOR_SET_ASSOCIATION(mVertexList);
  36. VECTOR_SET_ASSOCIATION(mIndexList);
  37. VECTOR_SET_ASSOCIATION(mPlaneList);
  38. VECTOR_SET_ASSOCIATION(mPolyList);
  39. mIndexList.reserve(100);
  40. mCurrObject = NULL;
  41. mBaseMatrix = MatrixF::Identity;
  42. mMatrix = MatrixF::Identity;
  43. mTransformMatrix = MatrixF::Identity;
  44. mScale.set(1.0f, 1.0f, 1.0f);
  45. mPlaneTransformer.setIdentity();
  46. mInterestNormalRegistered = false;
  47. }
  48. OptimizedPolyList::~OptimizedPolyList()
  49. {
  50. mPoints.clear();
  51. mNormals.clear();
  52. mUV0s.clear();
  53. mUV1s.clear();
  54. mVertexList.clear();
  55. mIndexList.clear();
  56. mPlaneList.clear();
  57. mPolyList.clear();
  58. }
  59. //----------------------------------------------------------------------------
  60. void OptimizedPolyList::clear()
  61. {
  62. mPoints.clear();
  63. mNormals.clear();
  64. mUV0s.clear();
  65. mUV1s.clear();
  66. mVertexList.clear();
  67. mIndexList.clear();
  68. mPlaneList.clear();
  69. mPolyList.clear();
  70. }
  71. //----------------------------------------------------------------------------
  72. U32 OptimizedPolyList::insertPoint(const Point3F& point)
  73. {
  74. S32 retIdx = -1;
  75. // Apply the transform
  76. Point3F transPoint = point;
  77. transPoint *= mScale;
  78. mMatrix.mulP(transPoint);
  79. for (U32 i = 0; i < mPoints.size(); i++)
  80. {
  81. if (mPoints[i].equal(transPoint))
  82. {
  83. retIdx = i;
  84. break;
  85. }
  86. }
  87. if (retIdx == -1)
  88. {
  89. retIdx = mPoints.size();
  90. mPoints.push_back(transPoint);
  91. }
  92. return (U32)retIdx;
  93. }
  94. U32 OptimizedPolyList::insertNormal(const Point3F& normal)
  95. {
  96. S32 retIdx = -1;
  97. // Apply the transform
  98. Point3F transNormal;
  99. mMatrix.mulV( normal, &transNormal );
  100. for (U32 i = 0; i < mNormals.size(); i++)
  101. {
  102. if (mNormals[i].equal(transNormal))
  103. {
  104. retIdx = i;
  105. break;
  106. }
  107. }
  108. if (retIdx == -1)
  109. {
  110. retIdx = mNormals.size();
  111. mNormals.push_back(transNormal);
  112. }
  113. return (U32)retIdx;
  114. }
  115. U32 OptimizedPolyList::insertUV0(const Point2F& uv)
  116. {
  117. S32 retIdx = -1;
  118. for (U32 i = 0; i < mUV0s.size(); i++)
  119. {
  120. if (mUV0s[i].equal(uv))
  121. {
  122. retIdx = i;
  123. break;
  124. }
  125. }
  126. if (retIdx == -1)
  127. {
  128. retIdx = mUV0s.size();
  129. mUV0s.push_back(uv);
  130. }
  131. return (U32)retIdx;
  132. }
  133. U32 OptimizedPolyList::insertUV1(const Point2F& uv)
  134. {
  135. S32 retIdx = -1;
  136. for (U32 i = 0; i < mUV1s.size(); i++)
  137. {
  138. if (mUV1s[i].equal(uv))
  139. {
  140. retIdx = i;
  141. break;
  142. }
  143. }
  144. if (retIdx == -1)
  145. {
  146. retIdx = mUV1s.size();
  147. mUV1s.push_back(uv);
  148. }
  149. return (U32)retIdx;
  150. }
  151. U32 OptimizedPolyList::insertPlane(const PlaneF& plane)
  152. {
  153. S32 retIdx = -1;
  154. // Apply the transform
  155. PlaneF transPlane;
  156. mPlaneTransformer.transform(plane, transPlane);
  157. for (U32 i = 0; i < mPlaneList.size(); i++)
  158. {
  159. if (mPlaneList[i].equal(transPlane) &&
  160. mFabs( mPlaneList[i].d - transPlane.d ) < POINT_EPSILON)
  161. {
  162. retIdx = i;
  163. break;
  164. }
  165. }
  166. if (retIdx == -1)
  167. {
  168. retIdx = mPlaneList.size();
  169. mPlaneList.push_back(transPlane);
  170. }
  171. return (U32)retIdx;
  172. }
  173. U32 OptimizedPolyList::insertMaterial(BaseMatInstance* baseMat)
  174. {
  175. S32 retIdx = -1;
  176. if ( !baseMat )
  177. return retIdx;
  178. Material* mat = dynamic_cast<Material*>(baseMat->getMaterial());
  179. for (U32 i = 0; i < mMaterialList.size(); i++)
  180. {
  181. Material* testMat = dynamic_cast<Material*>(mMaterialList[i]->getMaterial());
  182. if (mat && testMat)
  183. {
  184. if (testMat == mat)
  185. {
  186. retIdx = i;
  187. break;
  188. }
  189. }
  190. else if (mMaterialList[i] == baseMat)
  191. {
  192. retIdx = i;
  193. break;
  194. }
  195. }
  196. if (retIdx == -1)
  197. {
  198. retIdx = mMaterialList.size();
  199. mMaterialList.push_back(baseMat);
  200. }
  201. return (U32)retIdx;
  202. }
  203. U32 OptimizedPolyList::insertVertex(const Point3F& point, const Point3F& normal,
  204. const Point2F& uv0, const Point2F& uv1)
  205. {
  206. VertIndex vert;
  207. vert.vertIdx = insertPoint(point);
  208. vert.normalIdx = insertNormal(normal);
  209. vert.uv0Idx = insertUV0(uv0);
  210. vert.uv1Idx = insertUV1(uv1);
  211. return mVertexList.push_back_unique(vert);
  212. }
  213. U32 OptimizedPolyList::addPoint(const Point3F& p)
  214. {
  215. return insertVertex(p);
  216. }
  217. U32 OptimizedPolyList::addPlane(const PlaneF& plane)
  218. {
  219. return insertPlane(plane);
  220. }
  221. //----------------------------------------------------------------------------
  222. void OptimizedPolyList::begin(BaseMatInstance* material, U32 surfaceKey)
  223. {
  224. mPolyList.increment();
  225. Poly& poly = mPolyList.last();
  226. poly.material = insertMaterial(material);
  227. poly.vertexStart = mIndexList.size();
  228. poly.surfaceKey = surfaceKey;
  229. poly.type = TriangleFan;
  230. poly.object = mCurrObject;
  231. }
  232. void OptimizedPolyList::begin(BaseMatInstance* material, U32 surfaceKey, PolyType type)
  233. {
  234. begin(material, surfaceKey);
  235. // Set the type
  236. mPolyList.last().type = type;
  237. }
  238. //----------------------------------------------------------------------------
  239. void OptimizedPolyList::plane(U32 v1, U32 v2, U32 v3)
  240. {
  241. /*
  242. AssertFatal(v1 < mPoints.size() && v2 < mPoints.size() && v3 < mPoints.size(),
  243. "OptimizedPolyList::plane(): Vertex indices are larger than vertex list size");
  244. mPolyList.last().plane = addPlane(PlaneF(mPoints[v1], mPoints[v2], mPoints[v3]));
  245. */
  246. mPolyList.last().plane = addPlane( PlaneF( mPoints[mVertexList[v1].vertIdx], mPoints[mVertexList[v2].vertIdx], mPoints[mVertexList[v3].vertIdx] ) );
  247. }
  248. void OptimizedPolyList::plane(const PlaneF& p)
  249. {
  250. mPolyList.last().plane = addPlane(p);
  251. }
  252. void OptimizedPolyList::plane(const U32 index)
  253. {
  254. AssertFatal(index < mPlaneList.size(), "Out of bounds index!");
  255. mPolyList.last().plane = index;
  256. }
  257. const PlaneF& OptimizedPolyList::getIndexedPlane(const U32 index)
  258. {
  259. AssertFatal(index < mPlaneList.size(), "Out of bounds index!");
  260. return mPlaneList[index];
  261. }
  262. //----------------------------------------------------------------------------
  263. void OptimizedPolyList::vertex(U32 vi)
  264. {
  265. mIndexList.push_back(vi);
  266. }
  267. void OptimizedPolyList::vertex(const Point3F& p)
  268. {
  269. mIndexList.push_back(addPoint(p));
  270. }
  271. void OptimizedPolyList::vertex(const Point3F& p,
  272. const Point3F& normal,
  273. const Point2F& uv0,
  274. const Point2F& uv1)
  275. {
  276. mIndexList.push_back(insertVertex(p, normal, uv0, uv1));
  277. }
  278. //----------------------------------------------------------------------------
  279. bool OptimizedPolyList::isEmpty() const
  280. {
  281. return !mPolyList.size();
  282. }
  283. void OptimizedPolyList::end()
  284. {
  285. Poly& poly = mPolyList.last();
  286. poly.vertexCount = mIndexList.size() - poly.vertexStart;
  287. }
  288. //----------------------------------------------------------------------------
  289. Polyhedron OptimizedPolyList::toPolyhedron() const
  290. {
  291. Polyhedron polyhedron;
  292. // Add the points, but filter out duplicates.
  293. Vector< S32 > pointRemap;
  294. pointRemap.setSize( mPoints.size() );
  295. pointRemap.fill( -1 );
  296. const U32 numPoints = mPoints.size();
  297. for( U32 i = 0; i < numPoints; ++ i )
  298. {
  299. bool isDuplicate = false;
  300. for( U32 npoint = 0; npoint < polyhedron.mPointList.size(); ++ npoint )
  301. {
  302. if( npoint == i )
  303. continue;
  304. if( !polyhedron.mPointList[ npoint ].equal( mPoints[ i ] ) )
  305. continue;
  306. pointRemap[ i ] = npoint;
  307. isDuplicate = true;
  308. }
  309. if( !isDuplicate )
  310. {
  311. pointRemap[ i ] = polyhedron.mPointList.size();
  312. polyhedron.mPointList.push_back( mPoints[ i ] );
  313. }
  314. }
  315. // Go through the polys and add all their edges and planes.
  316. // We will consolidate edges in a second pass.
  317. const U32 numPolys = mPolyList.size();
  318. for( U32 i = 0; i < numPolys; ++ i )
  319. {
  320. const Poly& poly = mPolyList[ i ];
  321. // Add the plane.
  322. const U32 polyIndex = polyhedron.mPlaneList.size();
  323. polyhedron.mPlaneList.push_back( mPlaneList[ poly.plane ] );
  324. // Account for polyhedrons expecting planes to
  325. // face inwards.
  326. polyhedron.mPlaneList.last().invert();
  327. // Gather remapped indices according to the
  328. // current polygon type.
  329. Vector< U32 > indexList;
  330. switch( poly.type )
  331. {
  332. case TriangleFan:
  333. AssertFatal( false, "TriangleFan conversion not implemented" );
  334. case TriangleStrip:
  335. AssertFatal( false, "TriangleStrip conversion not implemented" );
  336. case TriangleList:
  337. {
  338. Vector< Polyhedron::Edge > tempEdges;
  339. // Loop over the triangles and gather all unshared edges
  340. // in tempEdges. These are the exterior edges of the polygon.
  341. for( U32 n = poly.vertexStart; n < poly.vertexStart + poly.vertexCount; n += 3 )
  342. {
  343. U32 indices[ 3 ];
  344. // Get the remapped indices of the three vertices.
  345. indices[ 0 ] = pointRemap[ mVertexList[ mIndexList[ n + 0 ] ].vertIdx ];
  346. indices[ 1 ] = pointRemap[ mVertexList[ mIndexList[ n + 1 ] ].vertIdx ];
  347. indices[ 2 ] = pointRemap[ mVertexList[ mIndexList[ n + 2 ] ].vertIdx ];
  348. // Loop over the three edges.
  349. for( U32 d = 0; d < 3; ++ d )
  350. {
  351. U32 index1 = indices[ d ];
  352. U32 index2 = indices[ ( d + 1 ) % 3 ];
  353. // See if this edge is already in the list. If so,
  354. // it's a shared edge and thus an interior one. Remove
  355. // it.
  356. bool isShared = false;
  357. for( U32 nedge = 0; nedge < tempEdges.size(); ++ nedge )
  358. {
  359. Polyhedron::Edge& edge = tempEdges[ nedge ];
  360. if( ( edge.vertex[ 0 ] == index1 && edge.vertex[ 1 ] == index2 ) ||
  361. ( edge.vertex[ 0 ] == index2 && edge.vertex[ 1 ] == index1 ) )
  362. {
  363. tempEdges.erase( nedge );
  364. isShared = true;
  365. break;
  366. }
  367. }
  368. // If it wasn't in the list, add a new edge.
  369. if( !isShared )
  370. tempEdges.push_back(
  371. Polyhedron::Edge( -1, -1, index1, index2 )
  372. );
  373. }
  374. }
  375. // Walk the edges and gather consecutive indices.
  376. U32 currentEdge = 0;
  377. for( U32 n = 0; n < tempEdges.size(); ++ n )
  378. {
  379. // Add first vertex of edge.
  380. indexList.push_back( tempEdges[ currentEdge ].vertex[ 0 ] );
  381. // Find edge that begins at second vertex.
  382. for( U32 nedge = 0; nedge < tempEdges.size(); ++ nedge )
  383. {
  384. if( nedge == currentEdge )
  385. continue;
  386. if( tempEdges[ nedge ].vertex[ 0 ] == tempEdges[ currentEdge ].vertex[ 1 ] )
  387. {
  388. currentEdge = nedge;
  389. break;
  390. }
  391. }
  392. }
  393. }
  394. }
  395. // Create edges from the indices. Indices are CCW ordered and
  396. // we want CW order, so step everything in reverse.
  397. U32 lastIndex = 0;
  398. for( S32 n = indexList.size() - 1; n >= 0; -- n )
  399. {
  400. polyhedron.mEdgeList.push_back(
  401. Polyhedron::Edge(
  402. polyIndex, 0, // face1 filled later
  403. indexList[ lastIndex ], indexList[ n ]
  404. )
  405. );
  406. lastIndex = n;
  407. }
  408. }
  409. // Finally, consolidate the edge list by merging all edges that
  410. // are shared by polygons.
  411. for( U32 i = 0; i < polyhedron.mEdgeList.size(); ++ i )
  412. {
  413. Polyhedron::Edge& edge = polyhedron.mEdgeList[ i ];
  414. // Find the corresponding duplicate edge, if any, and merge
  415. // it into our current edge.
  416. for( U32 n = i + 1; n < polyhedron.mEdgeList.size(); ++ n )
  417. {
  418. const Polyhedron::Edge& thisEdge = polyhedron.mEdgeList[ n ];
  419. if( ( thisEdge.vertex[ 0 ] == edge.vertex[ 1 ] &&
  420. thisEdge.vertex[ 1 ] == edge.vertex[ 0 ] ) ||
  421. ( thisEdge.vertex[ 0 ] == edge.vertex[ 0 ] &&
  422. thisEdge.vertex[ 1 ] == edge.vertex[ 1 ] ) )
  423. {
  424. edge.face[ 1 ] = thisEdge.face[ 0 ];
  425. polyhedron.mEdgeList.erase( n );
  426. break;
  427. }
  428. }
  429. }
  430. return polyhedron;
  431. }