BsMeshUtility.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsMeshUtility.h"
  4. #include "BsVector3.h"
  5. #include "BsVector2.h"
  6. #include "BsPlane.h"
  7. namespace BansheeEngine
  8. {
  9. struct VertexFaces
  10. {
  11. UINT32* faces;
  12. UINT32 numFaces = 0;
  13. };
  14. struct VertexConnectivity
  15. {
  16. VertexConnectivity(UINT8* indices, UINT32 numVertices, UINT32 numFaces, UINT32 indexSize)
  17. :vertexFaces(nullptr), mMaxFacesPerVertex(0), mNumVertices(numVertices), mFaces(nullptr)
  18. {
  19. vertexFaces = bs_newN<VertexFaces>(numVertices);
  20. resizeFaceArray(10);
  21. for (UINT32 i = 0; i < numFaces; i++)
  22. {
  23. for (UINT32 j = 0; j < 3; j++)
  24. {
  25. UINT32 idx = i * 3 + j;
  26. UINT32 vertexIdx = 0;
  27. memcpy(&vertexIdx, indices + idx * indexSize, indexSize);
  28. assert(vertexIdx < mNumVertices);
  29. VertexFaces& faces = vertexFaces[vertexIdx];
  30. if (faces.numFaces >= mMaxFacesPerVertex)
  31. resizeFaceArray(mMaxFacesPerVertex * 2);
  32. faces.faces[faces.numFaces] = i;
  33. faces.numFaces++;
  34. }
  35. }
  36. }
  37. ~VertexConnectivity()
  38. {
  39. if (vertexFaces != nullptr)
  40. bs_deleteN(vertexFaces, mNumVertices);
  41. if (mFaces != nullptr)
  42. bs_free(mFaces);
  43. }
  44. VertexFaces* vertexFaces;
  45. private:
  46. void resizeFaceArray(UINT32 numFaces)
  47. {
  48. UINT32* newFaces = (UINT32*)bs_alloc(numFaces * mNumVertices * sizeof(UINT32));
  49. if (mFaces != nullptr)
  50. {
  51. for (UINT32 i = 0; i < mNumVertices; i++)
  52. memcpy(newFaces + (i * numFaces), mFaces + (i * mMaxFacesPerVertex), mMaxFacesPerVertex * sizeof(UINT32));
  53. bs_free(mFaces);
  54. }
  55. for (UINT32 i = 0; i < mNumVertices; i++)
  56. vertexFaces[i].faces = newFaces + (i * numFaces);
  57. mFaces = newFaces;
  58. mMaxFacesPerVertex = numFaces;
  59. }
  60. UINT32 mMaxFacesPerVertex;
  61. UINT32 mNumVertices;
  62. UINT32* mFaces;
  63. };
  64. /** Provides base methods required for clipping of arbitrary triangles. */
  65. class TriangleClipperBase // Implementation from: http://www.geometrictools.com/Documentation/ClipMesh.pdf
  66. {
  67. protected:
  68. /** Single vertex in the clipped mesh. */
  69. struct ClipVert
  70. {
  71. ClipVert() { }
  72. Vector3 point;
  73. Vector2 uv;
  74. float distance = 0.0f;
  75. UINT32 occurs = 0;
  76. bool visible = true;
  77. };
  78. /** Single edge in the clipped mesh. */
  79. struct ClipEdge
  80. {
  81. ClipEdge() { }
  82. UINT32 verts[2];
  83. Vector<UINT32> faces;
  84. bool visible = true;
  85. };
  86. /** Single polygon in the clipped mesh. */
  87. struct ClipFace
  88. {
  89. ClipFace() { }
  90. Vector<UINT32> edges;
  91. bool visible = true;
  92. Vector3 normal;
  93. };
  94. /** Contains vertices, edges and faces of the clipped mesh. */
  95. struct ClipMesh
  96. {
  97. ClipMesh() { }
  98. Vector<ClipVert> verts;
  99. Vector<ClipEdge> edges;
  100. Vector<ClipFace> faces;
  101. };
  102. protected:
  103. /**
  104. * Register all edges and faces, using the mesh vertices as a basis. Assumes vertices are not indexed and that
  105. * every three vertices form a face
  106. */
  107. void addEdgesAndFaces();
  108. /** Clips the current mesh with the provided plane. */
  109. INT32 clipByPlane(const Plane& plane);
  110. /** Clips vertices of the current mesh by the provided plane. */
  111. INT32 processVertices(const Plane& plane);
  112. /** Clips edges of the current mesh. processVertices() must be called beforehand. */
  113. void processEdges();
  114. /** Clips the faces (polygons) of the current mesh. processEdges() must be called beforehand. */
  115. void processFaces();
  116. /**
  117. * Returns a set of non-culled vertex indices for every visible face in the mesh. This should be called after
  118. * clipping operation is complete to retrieve valid vertices.
  119. */
  120. void getOrderedFaces(FrameVector<FrameVector<UINT32>>& sortedFaces);
  121. /** Returns a set of ordered and non-culled vertices for the provided face of the mesh */
  122. void getOrderedVertices(const ClipFace& face, UINT32* vertices);
  123. /** Calculates the normal for vertices related to the provided vertex indices. */
  124. Vector3 getNormal(UINT32* sortedVertices, UINT32 numVertices);
  125. /**
  126. * Checks is the polygon shape of the provided face open or closed. If open, returns true and outputs endpoints of
  127. * the polyline.
  128. */
  129. bool getOpenPolyline(ClipFace& face, UINT32& start, UINT32& end);
  130. ClipMesh mesh;
  131. };
  132. void TriangleClipperBase::addEdgesAndFaces()
  133. {
  134. UINT32 numTris = (UINT32)mesh.verts.size() / 3;
  135. UINT32 numEdges = numTris * 3;
  136. mesh.edges.resize(numEdges);
  137. mesh.faces.resize(numTris);
  138. for (UINT32 i = 0; i < numTris; i++)
  139. {
  140. UINT32 idx0 = i * 3 + 0;
  141. UINT32 idx1 = i * 3 + 1;
  142. UINT32 idx2 = i * 3 + 2;
  143. ClipEdge& clipEdge0 = mesh.edges[idx0];
  144. clipEdge0.verts[0] = idx0;
  145. clipEdge0.verts[1] = idx1;
  146. ClipEdge& clipEdge1 = mesh.edges[idx1];
  147. clipEdge1.verts[0] = idx1;
  148. clipEdge1.verts[1] = idx2;
  149. ClipEdge& clipEdge2 = mesh.edges[idx2];
  150. clipEdge2.verts[0] = idx2;
  151. clipEdge2.verts[1] = idx0;
  152. ClipFace& clipFace = mesh.faces[i];
  153. clipFace.edges.push_back(idx0);
  154. clipFace.edges.push_back(idx1);
  155. clipFace.edges.push_back(idx2);
  156. clipEdge0.faces.push_back(i);
  157. clipEdge1.faces.push_back(i);
  158. clipEdge2.faces.push_back(i);
  159. UINT32 verts[] = { idx0, idx1, idx2, idx0 };
  160. for (UINT32 j = 0; j < 3; j++)
  161. clipFace.normal += Vector3::cross(mesh.verts[verts[j]].point, mesh.verts[verts[j + 1]].point);
  162. clipFace.normal.normalize();
  163. }
  164. }
  165. INT32 TriangleClipperBase::clipByPlane(const Plane& plane)
  166. {
  167. int state = processVertices(plane);
  168. if (state == 1)
  169. return +1; // Nothing is clipped
  170. else if (state == -1)
  171. return -1; // Everything is clipped
  172. processEdges();
  173. processFaces();
  174. return 0;
  175. }
  176. INT32 TriangleClipperBase::processVertices(const Plane& plane)
  177. {
  178. static const float EPSILON = 0.00001f;
  179. // Compute signed distances from vertices to plane
  180. int positive = 0, negative = 0;
  181. for (UINT32 i = 0; i < (UINT32)mesh.verts.size(); i++)
  182. {
  183. ClipVert& vertex = mesh.verts[i];
  184. if (vertex.visible)
  185. {
  186. vertex.distance = Vector3::dot(plane.normal, vertex.point) - plane.d;
  187. if (vertex.distance >= EPSILON)
  188. {
  189. positive++;
  190. }
  191. else if (vertex.distance <= -EPSILON)
  192. {
  193. negative++;
  194. vertex.visible = false;
  195. }
  196. else
  197. {
  198. // Point on the plane within floating point tolerance
  199. vertex.distance = 0;
  200. }
  201. }
  202. }
  203. if (negative == 0)
  204. {
  205. // All vertices on nonnegative side, no clipping
  206. return +1;
  207. }
  208. if (positive == 0)
  209. {
  210. // All vertices on nonpositive side, everything clipped
  211. return -1;
  212. }
  213. return 0;
  214. }
  215. void TriangleClipperBase::processEdges()
  216. {
  217. for (UINT32 i = 0; i < (UINT32)mesh.edges.size(); i++)
  218. {
  219. ClipEdge& edge = mesh.edges[i];
  220. if (edge.visible)
  221. {
  222. const ClipVert& v0 = mesh.verts[edge.verts[0]];
  223. const ClipVert& v1 = mesh.verts[edge.verts[1]];
  224. float d0 = v0.distance;
  225. float d1 = v1.distance;
  226. if (d0 <= 0 && d1 <= 0)
  227. {
  228. // Edge is culled, remove edge from faces sharing it
  229. for (UINT32 j = 0; j < (UINT32)edge.faces.size(); j++)
  230. {
  231. ClipFace& face = mesh.faces[edge.faces[j]];
  232. auto iterFind = std::find(face.edges.begin(), face.edges.end(), i);
  233. if (iterFind != face.edges.end())
  234. {
  235. face.edges.erase(iterFind);
  236. if (face.edges.empty())
  237. face.visible = false;
  238. }
  239. }
  240. edge.visible = false;
  241. continue;
  242. }
  243. if (d0 >= 0 && d1 >= 0)
  244. {
  245. // Edge is on nonnegative side, faces retain the edge
  246. continue;
  247. }
  248. // The edge is split by the plane. Compute the point of intersection.
  249. // If the old edge is <V0,V1> and I is the intersection point, the new
  250. // edge is <V0,I> when d0 > 0 or <I,V1> when d1 > 0.
  251. float t = d0 / (d0 - d1);
  252. Vector3 intersectPt = (1 - t)*v0.point + t*v1.point;
  253. Vector2 intersectUv = (1 - t)*v0.uv + t*v1.uv;
  254. UINT32 newVertIdx = (UINT32)mesh.verts.size();
  255. mesh.verts.push_back(ClipVert());
  256. ClipVert& newVert = mesh.verts.back();
  257. newVert.point = intersectPt;
  258. newVert.uv = intersectUv;
  259. if (d0 > 0)
  260. mesh.edges[i].verts[1] = newVertIdx;
  261. else
  262. mesh.edges[i].verts[0] = newVertIdx;
  263. }
  264. }
  265. }
  266. void TriangleClipperBase::processFaces()
  267. {
  268. for (UINT32 i = 0; i < (UINT32)mesh.faces.size(); i++)
  269. {
  270. ClipFace& face = mesh.faces[i];
  271. if (face.visible)
  272. {
  273. // The edge is culled. If the edge is exactly on the clip
  274. // plane, it is possible that a visible triangle shares it.
  275. // The edge will be re-added during the face loop.
  276. for (UINT32 j = 0; j < (UINT32)face.edges.size(); j++)
  277. {
  278. ClipEdge& edge = mesh.edges[face.edges[j]];
  279. ClipVert& v0 = mesh.verts[edge.verts[0]];
  280. ClipVert& v1 = mesh.verts[edge.verts[1]];
  281. v0.occurs = 0;
  282. v1.occurs = 0;
  283. }
  284. }
  285. UINT32 start, end;
  286. if (getOpenPolyline(mesh.faces[i], start, end))
  287. {
  288. // Polyline is open, close it
  289. UINT32 closeEdgeIdx = (UINT32)mesh.edges.size();
  290. mesh.edges.push_back(ClipEdge());
  291. ClipEdge& closeEdge = mesh.edges.back();
  292. closeEdge.verts[0] = start;
  293. closeEdge.verts[1] = end;
  294. closeEdge.faces.push_back(i);
  295. face.edges.push_back(closeEdgeIdx);
  296. }
  297. }
  298. }
  299. bool TriangleClipperBase::getOpenPolyline(ClipFace& face, UINT32& start, UINT32& end)
  300. {
  301. // Count the number of occurrences of each vertex in the polyline. The
  302. // resulting "occurs" values must be 1 or 2.
  303. for (UINT32 i = 0; i < (UINT32)face.edges.size(); i++)
  304. {
  305. ClipEdge& edge = mesh.edges[face.edges[i]];
  306. if (edge.visible)
  307. {
  308. ClipVert& v0 = mesh.verts[edge.verts[0]];
  309. ClipVert& v1 = mesh.verts[edge.verts[1]];
  310. v0.occurs++;
  311. v1.occurs++;
  312. }
  313. }
  314. // Determine if the polyline is open
  315. bool gotStart = false;
  316. bool gotEnd = false;
  317. for (UINT32 i = 0; i < (UINT32)face.edges.size(); i++)
  318. {
  319. const ClipEdge& edge = mesh.edges[face.edges[i]];
  320. const ClipVert& v0 = mesh.verts[edge.verts[0]];
  321. const ClipVert& v1 = mesh.verts[edge.verts[1]];
  322. if (v0.occurs == 1)
  323. {
  324. if (!gotStart)
  325. {
  326. start = edge.verts[0];
  327. gotStart = true;
  328. }
  329. else if (!gotEnd)
  330. {
  331. end = edge.verts[0];
  332. gotEnd = true;
  333. }
  334. }
  335. if (v1.occurs == 1)
  336. {
  337. if (!gotStart)
  338. {
  339. start = edge.verts[1];
  340. gotStart = true;
  341. }
  342. else if (!gotEnd)
  343. {
  344. end = edge.verts[1];
  345. gotEnd = true;
  346. }
  347. }
  348. }
  349. return gotStart;
  350. }
  351. void TriangleClipperBase::getOrderedFaces(FrameVector<FrameVector<UINT32>>& sortedFaces)
  352. {
  353. for (UINT32 i = 0; i < (UINT32)mesh.faces.size(); i++)
  354. {
  355. const ClipFace& face = mesh.faces[i];
  356. if (face.visible)
  357. {
  358. // Get the ordered vertices of the face. The first and last
  359. // element of the array are the same since the polyline is
  360. // closed.
  361. UINT32 numSortedVerts = (UINT32)face.edges.size() + 1;
  362. UINT32* sortedVerts = (UINT32*)bs_stack_alloc(sizeof(UINT32) * numSortedVerts);
  363. getOrderedVertices(face, sortedVerts);
  364. FrameVector<UINT32> faceVerts;
  365. // The convention is that the vertices should be counterclockwise
  366. // ordered when viewed from the negative side of the plane of the
  367. // face. If you need the opposite convention, switch the
  368. // inequality in the if-else statement.
  369. Vector3 normal = getNormal(sortedVerts, numSortedVerts);
  370. if (Vector3::dot(mesh.faces[i].normal, normal) < 0)
  371. {
  372. // Clockwise, need to swap
  373. for (INT32 j = (INT32)numSortedVerts - 2; j >= 0; j--)
  374. faceVerts.push_back(sortedVerts[j]);
  375. }
  376. else
  377. {
  378. // Counterclockwise
  379. for (int j = 0; j <= (INT32)numSortedVerts - 2; j++)
  380. faceVerts.push_back(sortedVerts[j]);
  381. }
  382. sortedFaces.push_back(faceVerts);
  383. bs_stack_free(sortedVerts);
  384. }
  385. }
  386. }
  387. void TriangleClipperBase::getOrderedVertices(const ClipFace& face, UINT32* sortedVerts)
  388. {
  389. UINT32 numEdges = (UINT32)face.edges.size();
  390. UINT32* sortedEdges = (UINT32*)bs_stack_alloc(sizeof(UINT32) * numEdges);
  391. for (UINT32 i = 0; i < numEdges; i++)
  392. sortedEdges[i] = face.edges[i];
  393. // Bubble sort to arrange edges in contiguous order
  394. for (UINT32 i0 = 0, i1 = 1, choice = 1; i1 < numEdges - 1; i0 = i1, i1++)
  395. {
  396. const ClipEdge& edge0 = mesh.edges[sortedEdges[i0]];
  397. UINT32 current = edge0.verts[choice];
  398. for (UINT32 j = i1; j < numEdges; j++)
  399. {
  400. const ClipEdge& edge1 = mesh.edges[sortedEdges[j]];
  401. if (edge1.verts[0] == current || edge1.verts[1] == current)
  402. {
  403. std::swap(sortedEdges[i1], sortedEdges[j]);
  404. choice = 1;
  405. break;
  406. }
  407. }
  408. }
  409. // Add the first two vertices
  410. sortedVerts[0] = mesh.edges[sortedEdges[0]].verts[0];
  411. sortedVerts[1] = mesh.edges[sortedEdges[0]].verts[1];
  412. // Add the remaining vertices
  413. for (UINT32 i = 1; i < numEdges; i++)
  414. {
  415. const ClipEdge& edge = mesh.edges[sortedEdges[i]];
  416. if (edge.verts[0] == sortedVerts[i])
  417. sortedVerts[i + 1] = edge.verts[1];
  418. else
  419. sortedVerts[i + 1] = edge.verts[0];
  420. }
  421. bs_stack_free(sortedEdges);
  422. }
  423. Vector3 TriangleClipperBase::getNormal(UINT32* sortedVertices, UINT32 numVertices)
  424. {
  425. Vector3 normal;
  426. for (UINT32 i = 0; i <= numVertices - 2; i++)
  427. normal += Vector3::cross(mesh.verts[sortedVertices[i]].point, mesh.verts[sortedVertices[i + 1]].point);
  428. normal.normalize();
  429. return normal;
  430. }
  431. /** Clips two-dimensional triangles against a set of provided planes. */
  432. class TriangleClipper2D : public TriangleClipperBase
  433. {
  434. public:
  435. /** @copydoc MeshUtility::clip2D */
  436. void clip(UINT8* vertices, UINT8* uvs, UINT32 numTris, UINT32 vertexStride, const Vector<Plane>& clipPlanes,
  437. const std::function<void(Vector2*, Vector2*, UINT32)>& writeCallback);
  438. private:
  439. /** Converts clipped vertices back into triangles and outputs them via the provided callback. */
  440. void convertToMesh(const std::function<void(Vector2*, Vector2*, UINT32)>& writeCallback);
  441. static const int BUFFER_SIZE = 64 * 3; // Must be a multiple of three
  442. Vector2 vertexBuffer[BUFFER_SIZE];
  443. Vector2 uvBuffer[BUFFER_SIZE];
  444. };
  445. void TriangleClipper2D::clip(UINT8* vertices, UINT8* uvs, UINT32 numTris, UINT32 vertexStride, const Vector<Plane>& clipPlanes,
  446. const std::function<void(Vector2*, Vector2*, UINT32)>& writeCallback)
  447. {
  448. // Add vertices
  449. UINT32 numVertices = numTris * 3;
  450. mesh.verts.resize(numVertices);
  451. if (uvs != nullptr)
  452. {
  453. for (UINT32 i = 0; i < numVertices; i++)
  454. {
  455. ClipVert& clipVert = mesh.verts[i];
  456. Vector2 vector2D = *(Vector2*)(vertices + vertexStride * i);
  457. clipVert.point = Vector3(vector2D.x, vector2D.y, 0.0f);
  458. clipVert.uv = *(Vector2*)(uvs + vertexStride * i);
  459. }
  460. }
  461. else
  462. {
  463. for (UINT32 i = 0; i < numVertices; i++)
  464. {
  465. ClipVert& clipVert = mesh.verts[i];
  466. Vector2 vector2D = *(Vector2*)(vertices + vertexStride * i);
  467. clipVert.point = Vector3(vector2D.x, vector2D.y, 0.0f);
  468. }
  469. }
  470. addEdgesAndFaces();
  471. for (int i = 0; i < 4; i++)
  472. clipByPlane(clipPlanes[i]);
  473. convertToMesh(writeCallback);
  474. }
  475. void TriangleClipper2D::convertToMesh(const std::function<void(Vector2*, Vector2*, UINT32)>& writeCallback)
  476. {
  477. bs_frame_mark();
  478. {
  479. FrameVector<FrameVector<UINT32>> allFaces;
  480. getOrderedFaces(allFaces);
  481. // Note: Consider using Delaunay triangulation to avoid skinny triangles
  482. UINT32 numWritten = 0;
  483. assert(BUFFER_SIZE % 3 == 0);
  484. for (auto& face : allFaces)
  485. {
  486. for (UINT32 i = 0; i < (UINT32)face.size() - 2; i++)
  487. {
  488. const Vector3& v0 = mesh.verts[face[0]].point;
  489. const Vector3& v1 = mesh.verts[face[i + 1]].point;
  490. const Vector3& v2 = mesh.verts[face[i + 2]].point;
  491. vertexBuffer[numWritten] = Vector2(v0.x, v0.y);
  492. uvBuffer[numWritten] = mesh.verts[face[0]].uv;
  493. numWritten++;
  494. vertexBuffer[numWritten] = Vector2(v1.x, v1.y);
  495. uvBuffer[numWritten] = mesh.verts[face[i + 1]].uv;
  496. numWritten++;
  497. vertexBuffer[numWritten] = Vector2(v2.x, v2.y);
  498. uvBuffer[numWritten] = mesh.verts[face[i + 2]].uv;
  499. numWritten++;
  500. // Only need to check this here since we guarantee the buffer is in multiples of three
  501. if (numWritten >= BUFFER_SIZE)
  502. {
  503. writeCallback(vertexBuffer, uvBuffer, numWritten);
  504. numWritten = 0;
  505. }
  506. }
  507. }
  508. if (numWritten > 0)
  509. writeCallback(vertexBuffer, uvBuffer, numWritten);
  510. }
  511. bs_frame_clear();
  512. }
  513. /** Clips three-dimensional triangles against a set of provided planes. */
  514. class TriangleClipper3D : public TriangleClipperBase
  515. {
  516. public:
  517. /** @copydoc MeshUtility::clip3D */
  518. void clip(UINT8* vertices, UINT8* uvs, UINT32 numTris, UINT32 vertexStride, const Vector<Plane>& clipPlanes,
  519. const std::function<void(Vector3*, Vector2*, UINT32)>& writeCallback);
  520. private:
  521. /** Converts clipped vertices back into triangles and outputs them via the provided callback. */
  522. void convertToMesh(const std::function<void(Vector3*, Vector2*, UINT32)>& writeCallback);
  523. static const int BUFFER_SIZE = 64 * 3; // Must be a multiple of three
  524. Vector3 vertexBuffer[BUFFER_SIZE];
  525. Vector2 uvBuffer[BUFFER_SIZE];
  526. };
  527. void TriangleClipper3D::clip(UINT8* vertices, UINT8* uvs, UINT32 numTris, UINT32 vertexStride, const Vector<Plane>& clipPlanes,
  528. const std::function<void(Vector3*, Vector2*, UINT32)>& writeCallback)
  529. {
  530. // Add vertices
  531. UINT32 numVertices = numTris * 3;
  532. mesh.verts.resize(numVertices);
  533. if (uvs != nullptr)
  534. {
  535. for (UINT32 i = 0; i < numVertices; i++)
  536. {
  537. ClipVert& clipVert = mesh.verts[i];
  538. clipVert.point = *(Vector3*)(vertices + vertexStride * i);
  539. clipVert.uv = *(Vector2*)(uvs + vertexStride * i);
  540. }
  541. }
  542. else
  543. {
  544. for (UINT32 i = 0; i < numVertices; i++)
  545. {
  546. ClipVert& clipVert = mesh.verts[i];
  547. Vector2 vector2D = *(Vector2*)(vertices + vertexStride * i);
  548. clipVert.point = Vector3(vector2D.x, vector2D.y, 0.0f);
  549. }
  550. }
  551. addEdgesAndFaces();
  552. for (int i = 0; i < 4; i++)
  553. clipByPlane(clipPlanes[i]);
  554. convertToMesh(writeCallback);
  555. }
  556. void TriangleClipper3D::convertToMesh(const std::function<void(Vector3*, Vector2*, UINT32)>& writeCallback)
  557. {
  558. bs_frame_mark();
  559. {
  560. FrameVector<FrameVector<UINT32>> allFaces;
  561. getOrderedFaces(allFaces);
  562. // Note: Consider using Delaunay triangulation to avoid skinny triangles
  563. UINT32 numWritten = 0;
  564. assert(BUFFER_SIZE % 3 == 0);
  565. for (auto& face : allFaces)
  566. {
  567. for (UINT32 i = 0; i < (UINT32)face.size() - 2; i++)
  568. {
  569. vertexBuffer[numWritten] = mesh.verts[face[0]].point;
  570. uvBuffer[numWritten] = mesh.verts[face[0]].uv;
  571. numWritten++;
  572. vertexBuffer[numWritten] = mesh.verts[face[i + 1]].point;
  573. uvBuffer[numWritten] = mesh.verts[face[i + 1]].uv;
  574. numWritten++;
  575. vertexBuffer[numWritten] = mesh.verts[face[i + 2]].point;
  576. uvBuffer[numWritten] = mesh.verts[face[i + 2]].uv;
  577. numWritten++;
  578. // Only need to check this here since we guarantee the buffer is in multiples of three
  579. if (numWritten >= BUFFER_SIZE)
  580. {
  581. writeCallback(vertexBuffer, uvBuffer, numWritten);
  582. numWritten = 0;
  583. }
  584. }
  585. }
  586. if (numWritten > 0)
  587. writeCallback(vertexBuffer, uvBuffer, numWritten);
  588. }
  589. bs_frame_clear();
  590. }
  591. void MeshUtility::calculateNormals(Vector3* vertices, UINT8* indices, UINT32 numVertices,
  592. UINT32 numIndices, Vector3* normals, UINT32 indexSize)
  593. {
  594. UINT32 numFaces = numIndices / 3;
  595. Vector3* faceNormals = bs_newN<Vector3>(numFaces);
  596. for (UINT32 i = 0; i < numFaces; i++)
  597. {
  598. UINT32 triangle[3];
  599. memcpy(&triangle[0], indices + (i * 3 + 0) * indexSize, indexSize);
  600. memcpy(&triangle[1], indices + (i * 3 + 1) * indexSize, indexSize);
  601. memcpy(&triangle[2], indices + (i * 3 + 2) * indexSize, indexSize);
  602. Vector3 edgeA = vertices[triangle[1]] - vertices[triangle[0]];
  603. Vector3 edgeB = vertices[triangle[2]] - vertices[triangle[0]];
  604. faceNormals[i] = Vector3::normalize(Vector3::cross(edgeA, edgeB));
  605. // Note: Potentially don't normalize here in order to weigh the normals
  606. // by triangle size
  607. }
  608. VertexConnectivity connectivity(indices, numVertices, numFaces, indexSize);
  609. for (UINT32 i = 0; i < numVertices; i++)
  610. {
  611. VertexFaces& faces = connectivity.vertexFaces[i];
  612. for (UINT32 j = 0; j < faces.numFaces; j++)
  613. {
  614. UINT32 faceIdx = faces.faces[j];
  615. normals[i] += faceNormals[faceIdx];
  616. }
  617. normals[i].normalize();
  618. }
  619. bs_deleteN(faceNormals, numFaces);
  620. }
  621. void MeshUtility::calculateTangents(Vector3* vertices, Vector3* normals, Vector2* uv, UINT8* indices, UINT32 numVertices,
  622. UINT32 numIndices, Vector3* tangents, Vector3* bitangents, UINT32 indexSize)
  623. {
  624. UINT32 numFaces = numIndices / 3;
  625. Vector3* faceTangents = bs_newN<Vector3>(numFaces);
  626. Vector3* faceBitangents = bs_newN<Vector3>(numFaces);
  627. for (UINT32 i = 0; i < numFaces; i++)
  628. {
  629. UINT32 triangle[3];
  630. memcpy(&triangle[0], indices + (i * 3 + 0) * indexSize, indexSize);
  631. memcpy(&triangle[1], indices + (i * 3 + 1) * indexSize, indexSize);
  632. memcpy(&triangle[2], indices + (i * 3 + 2) * indexSize, indexSize);
  633. Vector3 p0 = vertices[triangle[0]];
  634. Vector3 p1 = vertices[triangle[1]];
  635. Vector3 p2 = vertices[triangle[2]];
  636. Vector2 uv0 = uv[triangle[0]];
  637. Vector2 uv1 = uv[triangle[1]];
  638. Vector2 uv2 = uv[triangle[2]];
  639. Vector3 q0 = p1 - p0;
  640. Vector3 q1 = p2 - p0;
  641. Vector2 s;
  642. s.x = uv1.x - uv0.x;
  643. s.y = uv2.x - uv0.x;
  644. Vector2 t;
  645. t.x = uv1.y - uv0.y;
  646. t.y = uv2.y - uv0.y;
  647. float denom = s.x*t.y - s.y * t.x;
  648. if (fabs(denom) >= 0e-8f)
  649. {
  650. float r = 1.0f / denom;
  651. s *= r;
  652. t *= r;
  653. faceTangents[i] = t.y * q0 - t.x * q1;
  654. faceBitangents[i] = s.x * q0 - s.y * q1;
  655. faceTangents[i].normalize();
  656. faceBitangents[i].normalize();
  657. }
  658. // Note: Potentially don't normalize here in order to weigh the normals
  659. // by triangle size
  660. }
  661. VertexConnectivity connectivity(indices, numVertices, numFaces, indexSize);
  662. for (UINT32 i = 0; i < numVertices; i++)
  663. {
  664. VertexFaces& faces = connectivity.vertexFaces[i];
  665. for (UINT32 j = 0; j < faces.numFaces; j++)
  666. {
  667. UINT32 faceIdx = faces.faces[j];
  668. tangents[i] += faceTangents[faceIdx];
  669. bitangents[i] += faceBitangents[faceIdx];
  670. }
  671. tangents[i].normalize();
  672. bitangents[i].normalize();
  673. // Orthonormalize
  674. float dot0 = normals[i].dot(tangents[i]);
  675. tangents[i] -= dot0*normals[i];
  676. tangents[i].normalize();
  677. float dot1 = tangents[i].dot(bitangents[i]);
  678. dot0 = normals[i].dot(bitangents[i]);
  679. bitangents[i] -= dot0*normals[i] + dot1*tangents[i];
  680. bitangents[i].normalize();
  681. }
  682. bs_deleteN(faceTangents, numFaces);
  683. bs_deleteN(faceBitangents, numFaces);
  684. // TODO - Consider weighing tangents by triangle size and/or edge angles
  685. }
  686. void MeshUtility::calculateTangentSpace(Vector3* vertices, Vector2* uv, UINT8* indices, UINT32 numVertices,
  687. UINT32 numIndices, Vector3* normals, Vector3* tangents, Vector3* bitangents, UINT32 indexSize)
  688. {
  689. calculateNormals(vertices, indices, numVertices, numIndices, normals, indexSize);
  690. calculateTangents(vertices, normals, uv, indices, numVertices, numIndices, tangents, bitangents, indexSize);
  691. }
  692. void MeshUtility::clip2D(UINT8* vertices, UINT8* uvs, UINT32 numTris, UINT32 vertexStride, const Vector<Plane>& clipPlanes,
  693. const std::function<void(Vector2*, Vector2*, UINT32)>& writeCallback)
  694. {
  695. TriangleClipper2D clipper;
  696. clipper.clip(vertices, uvs, numTris, vertexStride, clipPlanes, writeCallback);
  697. }
  698. void MeshUtility::clip3D(UINT8* vertices, UINT8* uvs, UINT32 numTris, UINT32 vertexStride, const Vector<Plane>& clipPlanes,
  699. const std::function<void(Vector3*, Vector2*, UINT32)>& writeCallback)
  700. {
  701. TriangleClipper3D clipper;
  702. clipper.clip(vertices, uvs, numTris, vertexStride, clipPlanes, writeCallback);
  703. }
  704. }