BsShapeMeshes3D.cpp 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsShapeMeshes3D.h"
  4. #include "BsRect2.h"
  5. #include "BsMesh.h"
  6. #include "BsTime.h"
  7. #include "BsVector2.h"
  8. #include "BsQuaternion.h"
  9. #include "BsSphere.h"
  10. #include "BsMaterial.h"
  11. #include "BsPass.h"
  12. #include "BsCoreApplication.h"
  13. #include "BsRenderQueue.h"
  14. #include "BsException.h"
  15. #include "BsCCamera.h"
  16. #include "BsBuiltinResources.h"
  17. #include "BsVertexDataDesc.h"
  18. // DEBUG ONLY
  19. #include "BsDebug.h"
  20. namespace BansheeEngine
  21. {
  22. const UINT32 ShapeMeshes3D::NUM_VERTICES_AA_LINE = 8;
  23. const UINT32 ShapeMeshes3D::NUM_INDICES_AA_LINE = 30;
  24. inline UINT8* writeVector3(UINT8* buffer, UINT32 stride, const Vector3& value)
  25. {
  26. *(Vector3*)buffer = value;
  27. return buffer + stride;
  28. }
  29. void ShapeMeshes3D::wireAABox(const AABox& box, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
  30. {
  31. UINT32* indexData = meshData->getIndices32();
  32. UINT8* positionData = meshData->getElementData(VES_POSITION);
  33. assert((vertexOffset + 8) <= meshData->getNumVertices());
  34. assert((indexOffset + 24) <= meshData->getNumIndices());
  35. wireAABox(box, positionData, vertexOffset, meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset);
  36. }
  37. void ShapeMeshes3D::solidAABox(const AABox& box, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
  38. {
  39. UINT32* indexData = meshData->getIndices32();
  40. UINT8* positionData = meshData->getElementData(VES_POSITION);
  41. UINT8* normalData = meshData->getElementData(VES_NORMAL);
  42. assert((vertexOffset + 24) <= meshData->getNumVertices());
  43. assert((indexOffset + 36) <= meshData->getNumIndices());
  44. solidAABox(box, positionData, normalData, vertexOffset, meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset);
  45. }
  46. void ShapeMeshes3D::wireSphere(const Sphere& sphere, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset, UINT32 quality)
  47. {
  48. UINT32* indexData = meshData->getIndices32();
  49. UINT8* positionData = meshData->getElementData(VES_POSITION);
  50. UINT32 requiredNumVertices, requiredNumIndices;
  51. getNumElementsWireSphere(quality, requiredNumVertices, requiredNumIndices);
  52. assert((vertexOffset + requiredNumVertices) <= meshData->getNumVertices());
  53. assert((indexOffset + requiredNumIndices) <= meshData->getNumIndices());
  54. UINT32 verticesPerArc = (quality + 1) * 5;
  55. UINT32 indicesPerArc = (verticesPerArc - 1) * 2;
  56. wireDisc(sphere.getCenter(), sphere.getRadius(), Vector3::UNIT_X, meshData,
  57. vertexOffset, indexOffset, quality);
  58. wireDisc(sphere.getCenter(), sphere.getRadius(), Vector3::UNIT_Y, meshData,
  59. vertexOffset + verticesPerArc, indexOffset + indicesPerArc, quality);
  60. wireDisc(sphere.getCenter(), sphere.getRadius(), Vector3::UNIT_Z, meshData,
  61. vertexOffset + verticesPerArc * 2, indexOffset + indicesPerArc * 2, quality);
  62. }
  63. void ShapeMeshes3D::solidSphere(const Sphere& sphere, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset, UINT32 quality)
  64. {
  65. UINT32* indexData = meshData->getIndices32();
  66. UINT8* positionData = meshData->getElementData(VES_POSITION);
  67. UINT8* normalData = meshData->getElementData(VES_NORMAL);
  68. UINT32 requiredNumVertices, requiredNumIndices;
  69. getNumElementsSphere(quality, requiredNumVertices, requiredNumIndices);
  70. assert((vertexOffset + requiredNumVertices) <= meshData->getNumVertices());
  71. assert((indexOffset + requiredNumIndices) <= meshData->getNumIndices());
  72. solidSphere(sphere, positionData, normalData, vertexOffset,
  73. meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset, quality);
  74. }
  75. void ShapeMeshes3D::wireDisc(const Vector3& center, float radius, const Vector3& normal, const MeshDataPtr& meshData,
  76. UINT32 vertexOffset, UINT32 indexOffset, UINT32 quality)
  77. {
  78. wireArc(center, radius, normal, Degree(0), Degree(360), meshData, vertexOffset, indexOffset, quality);
  79. }
  80. void ShapeMeshes3D::solidDisc(const Vector3& center, float radius, const Vector3& normal, const MeshDataPtr& meshData,
  81. UINT32 vertexOffset, UINT32 indexOffset, UINT32 quality)
  82. {
  83. solidArc(center, radius, normal, Degree(0), Degree(360), meshData, vertexOffset, indexOffset, quality);
  84. }
  85. void ShapeMeshes3D::wireArc(const Vector3& center, float radius, const Vector3& normal, Degree startAngle, Degree amountAngle,
  86. const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset, UINT32 quality)
  87. {
  88. UINT32* indexData = meshData->getIndices32();
  89. UINT8* positionData = meshData->getElementData(VES_POSITION);
  90. UINT32 requiredNumVertices, requiredNumIndices;
  91. getNumElementsWireArc(quality, requiredNumVertices, requiredNumIndices);
  92. assert((vertexOffset + requiredNumVertices) <= meshData->getNumVertices());
  93. assert((indexOffset + requiredNumIndices) <= meshData->getNumIndices());
  94. wireArc(center, radius, normal, startAngle, amountAngle, positionData, vertexOffset,
  95. meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset, quality);
  96. }
  97. void ShapeMeshes3D::solidArc(const Vector3& center, float radius, const Vector3& normal, Degree startAngle, Degree amountAngle,
  98. const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset, UINT32 quality)
  99. {
  100. UINT32* indexData = meshData->getIndices32();
  101. UINT8* positionData = meshData->getElementData(VES_POSITION);
  102. UINT8* normalData = meshData->getElementData(VES_NORMAL);
  103. UINT32 requiredNumVertices, requiredNumIndices;
  104. getNumElementsArc(quality, requiredNumVertices, requiredNumIndices);
  105. assert((vertexOffset + requiredNumVertices) <= meshData->getNumVertices());
  106. assert((indexOffset + requiredNumIndices) <= meshData->getNumIndices());
  107. solidArc(center, radius, normal, startAngle, amountAngle, positionData, normalData, vertexOffset,
  108. meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset, quality);
  109. }
  110. void ShapeMeshes3D::wireFrustum(const Vector3& position, float aspect, Degree FOV, float near, float far,
  111. const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
  112. {
  113. UINT32* indexData = meshData->getIndices32();
  114. UINT8* positionData = meshData->getElementData(VES_POSITION);
  115. assert((vertexOffset + 8) <= meshData->getNumVertices());
  116. assert((indexOffset + 24) <= meshData->getNumIndices());
  117. wireFrustum(position, aspect, FOV, near, far, positionData, vertexOffset, meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset);
  118. }
  119. void ShapeMeshes3D::solidCone(const Vector3& base, const Vector3& normal, float height, float radius,
  120. const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset, UINT32 quality)
  121. {
  122. UINT32* indexData = meshData->getIndices32();
  123. UINT8* positionData = meshData->getElementData(VES_POSITION);
  124. UINT8* normalData = meshData->getElementData(VES_NORMAL);
  125. UINT32 requiredNumVertices, requiredNumIndices;
  126. getNumElementsCone(quality, requiredNumVertices, requiredNumIndices);
  127. assert((vertexOffset + requiredNumVertices) <= meshData->getNumVertices());
  128. assert((indexOffset + requiredNumIndices) <= meshData->getNumIndices());
  129. solidCone(base, normal, height, radius, positionData, normalData, vertexOffset,
  130. meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset, quality);
  131. }
  132. void ShapeMeshes3D::solidQuad(const Rect3& area, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
  133. {
  134. UINT32* indexData = meshData->getIndices32();
  135. UINT8* positionData = meshData->getElementData(VES_POSITION);
  136. UINT8* normalData = meshData->getElementData(VES_NORMAL);
  137. assert((vertexOffset + 8) <= meshData->getNumVertices());
  138. assert((indexOffset + 12) <= meshData->getNumIndices());
  139. solidQuad(area, positionData, normalData, vertexOffset,
  140. meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset);
  141. }
  142. void ShapeMeshes3D::pixelLine(const Vector3& a, const Vector3& b, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
  143. {
  144. UINT32* indexData = meshData->getIndices32();
  145. UINT8* positionData = meshData->getElementData(VES_POSITION);
  146. assert((vertexOffset + 2) <= meshData->getNumVertices());
  147. assert((indexOffset + 2) <= meshData->getNumIndices());
  148. pixelLine(a, b, positionData, vertexOffset, meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset);
  149. }
  150. void ShapeMeshes3D::antialiasedLine(const Vector3& a, const Vector3& b, const Vector3& up, float width, float borderWidth,
  151. const Color& color, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
  152. {
  153. UINT32* indexData = meshData->getIndices32();
  154. UINT8* positionData = meshData->getElementData(VES_POSITION);
  155. UINT8* colorData = meshData->getElementData(VES_COLOR);
  156. assert((vertexOffset + NUM_VERTICES_AA_LINE) <= meshData->getNumVertices());
  157. assert((indexOffset + NUM_INDICES_AA_LINE) <= meshData->getNumIndices());
  158. antialiasedLine(a, b, up, width, borderWidth, color, positionData, colorData, vertexOffset, meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset);
  159. }
  160. void ShapeMeshes3D::pixelLineList(const Vector<Vector3>& linePoints, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
  161. {
  162. assert(linePoints.size() % 2 == 0);
  163. assert((vertexOffset + linePoints.size() * 2) <= meshData->getNumVertices());
  164. assert((indexOffset + linePoints.size() * 2) <= meshData->getNumIndices());
  165. UINT32 curVertOffset = vertexOffset;
  166. UINT32 curIdxOffset = indexOffset;
  167. UINT32* indexData = meshData->getIndices32();
  168. UINT8* positionData = meshData->getElementData(VES_POSITION);
  169. UINT32 numPoints = (UINT32)linePoints.size();
  170. for (UINT32 i = 0; i < numPoints; i += 2)
  171. {
  172. pixelLine(linePoints[i], linePoints[i + 1], positionData, curVertOffset, meshData->getVertexDesc()->getVertexStride(), indexData, curIdxOffset);
  173. curVertOffset += 2;
  174. curIdxOffset += 2;
  175. }
  176. }
  177. void ShapeMeshes3D::antialiasedLineList(const Vector<Vector3>& linePoints, const Vector3& up, float width, float borderWidth,
  178. const Color& color, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
  179. {
  180. assert(linePoints.size() % 2 == 0);
  181. assert((vertexOffset + linePoints.size() * 4) <= meshData->getNumVertices());
  182. assert((indexOffset + linePoints.size() * 15) <= meshData->getNumIndices());
  183. UINT32 curVertOffset = vertexOffset;
  184. UINT32 curIdxOffset = indexOffset;
  185. UINT32* indexData = meshData->getIndices32();
  186. UINT8* positionData = meshData->getElementData(VES_POSITION);
  187. UINT8* colorData = meshData->getElementData(VES_COLOR);
  188. UINT32 numPoints = (UINT32)linePoints.size();
  189. for (UINT32 i = 0; i < numPoints; i += 2)
  190. {
  191. antialiasedLine(linePoints[i], linePoints[i + 1], up, width, borderWidth, color, positionData, colorData, curVertOffset, meshData->getVertexDesc()->getVertexStride(), indexData, curIdxOffset);
  192. curVertOffset += NUM_VERTICES_AA_LINE;
  193. curIdxOffset += NUM_INDICES_AA_LINE;
  194. }
  195. }
  196. /************************************************************************/
  197. /* ELEMENT COUNT */
  198. /************************************************************************/
  199. void ShapeMeshes3D::getNumElementsAABox(UINT32& numVertices, UINT32& numIndices)
  200. {
  201. numVertices = 24;
  202. numIndices = 36;
  203. }
  204. void ShapeMeshes3D::getNumElementsWireAABox(UINT32& numVertices, UINT32& numIndices)
  205. {
  206. numVertices = 8;
  207. numIndices = 24;
  208. }
  209. void ShapeMeshes3D::getNumElementsSphere(UINT32 quality, UINT32& numVertices, UINT32& numIndices)
  210. {
  211. numVertices = 20 * (3 * ((UINT32)std::pow(4, quality)));
  212. numIndices = numVertices;
  213. }
  214. void ShapeMeshes3D::getNumElementsWireSphere(UINT32 quality, UINT32& numVertices, UINT32& numIndices)
  215. {
  216. getNumElementsWireArc(quality, numVertices, numIndices);
  217. numVertices *= 3;
  218. numIndices *= 3;
  219. }
  220. void ShapeMeshes3D::getNumElementsArc(UINT32 quality, UINT32& numVertices, UINT32& numIndices)
  221. {
  222. numVertices = ((quality + 1) * 5 + 1) * 2;
  223. numIndices = ((quality + 1) * 5 - 1) * 6;
  224. }
  225. void ShapeMeshes3D::getNumElementsWireArc(UINT32 quality, UINT32& numVertices, UINT32& numIndices)
  226. {
  227. numVertices = (quality + 1) * 5;
  228. numIndices = ((quality + 1) * 5 - 1) * 2;
  229. }
  230. void ShapeMeshes3D::getNumElementsDisc(UINT32 quality, UINT32& numVertices, UINT32& numIndices)
  231. {
  232. getNumElementsArc(quality, numVertices, numIndices);
  233. }
  234. void ShapeMeshes3D::getNumElementsWireDisc(UINT32 quality, UINT32& numVertices, UINT32& numIndices)
  235. {
  236. getNumElementsWireArc(quality, numVertices, numIndices);
  237. }
  238. void ShapeMeshes3D::getNumElementsCone(UINT32 quality, UINT32& numVertices, UINT32& numIndices)
  239. {
  240. numVertices = ((quality + 1) * 4) * 3 + 1;
  241. numIndices = ((quality + 1) * 4) * 6;
  242. }
  243. void ShapeMeshes3D::getNumElementsQuad(UINT32& numVertices, UINT32& numIndices)
  244. {
  245. numVertices = 8;
  246. numIndices = 12;
  247. }
  248. void ShapeMeshes3D::getNumElementsFrustum(UINT32& numVertices, UINT32& numIndices)
  249. {
  250. numVertices = 8;
  251. numIndices = 36;
  252. }
  253. void ShapeMeshes3D::wireAABox(const AABox& box, UINT8* outVertices, UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset)
  254. {
  255. outVertices += vertexOffset * vertexStride;
  256. outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_LEFT_BOTTOM));
  257. outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_RIGHT_BOTTOM));
  258. outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_RIGHT_TOP));
  259. outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_LEFT_TOP));
  260. outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_RIGHT_BOTTOM));
  261. outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_LEFT_BOTTOM));
  262. outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_LEFT_TOP));
  263. outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_RIGHT_TOP));
  264. outIndices += indexOffset;
  265. // Front
  266. outIndices[0] = vertexOffset + 0;
  267. outIndices[1] = vertexOffset + 1;
  268. outIndices[2] = vertexOffset + 1;
  269. outIndices[3] = vertexOffset + 2;
  270. outIndices[4] = vertexOffset + 2;
  271. outIndices[5] = vertexOffset + 3;
  272. outIndices[6] = vertexOffset + 3;
  273. outIndices[7] = vertexOffset + 0;
  274. // Center
  275. outIndices[8] = vertexOffset + 0;
  276. outIndices[9] = vertexOffset + 5;
  277. outIndices[10] = vertexOffset + 1;
  278. outIndices[11] = vertexOffset + 4;
  279. outIndices[12] = vertexOffset + 2;
  280. outIndices[13] = vertexOffset + 7;
  281. outIndices[14] = vertexOffset + 3;
  282. outIndices[15] = vertexOffset + 6;
  283. // Back
  284. outIndices[16] = vertexOffset + 4;
  285. outIndices[17] = vertexOffset + 5;
  286. outIndices[18] = vertexOffset + 5;
  287. outIndices[19] = vertexOffset + 6;
  288. outIndices[20] = vertexOffset + 6;
  289. outIndices[21] = vertexOffset + 7;
  290. outIndices[22] = vertexOffset + 7;
  291. outIndices[23] = vertexOffset + 4;
  292. }
  293. void ShapeMeshes3D::solidAABox(const AABox& box, UINT8* outVertices, UINT8* outNormals, UINT32 vertexOffset, UINT32 vertexStride,
  294. UINT32* outIndices, UINT32 indexOffset)
  295. {
  296. outVertices += (vertexOffset * vertexStride);
  297. Vector3* corners = (Vector3*)outVertices;
  298. // Front face
  299. outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_LEFT_BOTTOM));
  300. outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_RIGHT_BOTTOM));
  301. outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_RIGHT_TOP));
  302. outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_LEFT_TOP));
  303. // Back face
  304. outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_RIGHT_BOTTOM));
  305. outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_LEFT_BOTTOM));
  306. outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_LEFT_TOP));
  307. outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_RIGHT_TOP));
  308. // Left face
  309. outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_LEFT_BOTTOM));
  310. outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_LEFT_BOTTOM));
  311. outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_LEFT_TOP));
  312. outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_LEFT_TOP));
  313. // Right face
  314. outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_RIGHT_BOTTOM));
  315. outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_RIGHT_BOTTOM));
  316. outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_RIGHT_TOP));
  317. outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_RIGHT_TOP));
  318. // Top face
  319. outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_LEFT_TOP));
  320. outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_LEFT_TOP));
  321. outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_RIGHT_TOP));
  322. outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_RIGHT_TOP));
  323. // Bottom face
  324. outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_LEFT_BOTTOM));
  325. outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::FAR_RIGHT_BOTTOM));
  326. outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_RIGHT_BOTTOM));
  327. outVertices = writeVector3(outVertices, vertexStride, box.getCorner(AABox::NEAR_LEFT_BOTTOM));
  328. static const Vector3 faceNormals[6] =
  329. {
  330. Vector3(0, 0, 1),
  331. Vector3(0, 0, -1),
  332. Vector3(-1, 0, 0),
  333. Vector3(1, 0, 0),
  334. Vector3(0, 1, 0),
  335. Vector3(0, -1, 0)
  336. };
  337. outNormals += (vertexOffset * vertexStride);
  338. for (UINT32 face = 0; face < 6; face++)
  339. {
  340. outNormals = writeVector3(outNormals, vertexStride, faceNormals[face]);
  341. outNormals = writeVector3(outNormals, vertexStride, faceNormals[face]);
  342. outNormals = writeVector3(outNormals, vertexStride, faceNormals[face]);
  343. outNormals = writeVector3(outNormals, vertexStride, faceNormals[face]);
  344. }
  345. UINT32* indices = outIndices + indexOffset;
  346. for (UINT32 face = 0; face < 6; face++)
  347. {
  348. UINT32 faceVertOffset = vertexOffset + face * 4;
  349. indices[face * 6 + 0] = faceVertOffset + 2;
  350. indices[face * 6 + 1] = faceVertOffset + 1;
  351. indices[face * 6 + 2] = faceVertOffset + 0;
  352. indices[face * 6 + 3] = faceVertOffset + 0;
  353. indices[face * 6 + 4] = faceVertOffset + 3;
  354. indices[face * 6 + 5] = faceVertOffset + 2;
  355. }
  356. }
  357. void ShapeMeshes3D::solidSphere(const Sphere& sphere, UINT8* outVertices, UINT8* outNormals, UINT32 vertexOffset,
  358. UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset, UINT32 quality)
  359. {
  360. // Create icosahedron
  361. static const float x = 0.525731112119133606f;
  362. static const float z = 0.850650808352039932f;
  363. static const Vector3 vertices[12] =
  364. {
  365. Vector3(-x, 0.0f, z),
  366. Vector3(x, 0.0f, z),
  367. Vector3(-x, 0.0f, -z),
  368. Vector3(x, 0.0f, -z),
  369. Vector3(0.0f, z, x),
  370. Vector3(0.0f, z, -x),
  371. Vector3(0.0f, -z, x),
  372. Vector3(0.0f, -z, -x),
  373. Vector3(z, x, 0.0f),
  374. Vector3(-z, x, 0.0f),
  375. Vector3(z, -x, 0.0f),
  376. Vector3(-z, -x, 0.0f)
  377. };
  378. static const UINT32 triangles[20][3] =
  379. {
  380. { 0, 4, 1 }, { 0, 9, 4 }, { 9, 5, 4 }, { 4, 5, 8 },
  381. { 4, 8, 1 }, { 8, 10, 1 }, { 8, 3, 10 }, { 5, 3, 8 },
  382. { 5, 2, 3 }, { 2, 7, 3 }, { 7, 10, 3 }, { 7, 6, 10 },
  383. { 7, 11, 6 }, { 11, 0, 6 }, { 0, 1, 6 }, { 6, 1, 10 },
  384. { 9, 0, 11 }, { 9, 11, 2 }, { 9, 2, 5 }, { 7, 2, 11 }
  385. };
  386. // Tessellate it
  387. UINT32 curVertOffset = vertexOffset;
  388. for (int i = 0; i < 20; ++i)
  389. {
  390. curVertOffset += subdivideTriangleOnSphere(sphere.getCenter(), sphere.getRadius(), quality,
  391. vertices[triangles[i][2]], vertices[triangles[i][1]], vertices[triangles[i][0]],
  392. outVertices, outNormals, curVertOffset, vertexStride);
  393. }
  394. // Create indices
  395. outIndices += indexOffset;
  396. UINT32 numIndices = 20 * (3 * (UINT32)std::pow(4, quality));
  397. for (UINT32 i = 0; i < numIndices; i += 3)
  398. {
  399. outIndices[i] = vertexOffset + i + 2;
  400. outIndices[i + 1] = vertexOffset + i + 1;
  401. outIndices[i + 2] = vertexOffset + i + 0;
  402. }
  403. }
  404. void ShapeMeshes3D::wireArc(const Vector3& center, float radius, const Vector3& normal, Degree startAngle, Degree amountAngle,
  405. UINT8* outVertices, UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset, UINT32 quality)
  406. {
  407. UINT32 numVertices = (quality + 1) * 5;
  408. generateArcVertices(center, normal, radius, startAngle, amountAngle,
  409. numVertices, outVertices, vertexOffset, vertexStride);
  410. outIndices += indexOffset;
  411. UINT32 numLines = numVertices - 1;
  412. for (UINT32 i = 0; i < numLines; i++)
  413. {
  414. outIndices[i * 2 + 0] = vertexOffset + i;
  415. outIndices[i * 2 + 1] = vertexOffset + i + 1;
  416. }
  417. }
  418. void ShapeMeshes3D::solidArc(const Vector3& center, float radius, const Vector3& normal, Degree startAngle, Degree amountAngle,
  419. UINT8* outVertices, UINT8* outNormals, UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset, UINT32 quality)
  420. {
  421. outVertices += vertexOffset * vertexStride;
  422. outNormals += vertexOffset * vertexStride;
  423. outIndices += indexOffset;
  424. bool reverseOrder = amountAngle.valueDegrees() < 0.0f;
  425. Vector3 visibleNormal = normal;
  426. outVertices = writeVector3(outVertices, vertexStride, center);
  427. outNormals = writeVector3(outNormals, vertexStride, visibleNormal);
  428. UINT32 numArcVertices = (quality + 1) * 5;
  429. generateArcVertices(center, normal, radius, startAngle, amountAngle,
  430. numArcVertices, outVertices, vertexOffset, vertexStride);
  431. UINT8* otherSideVertices = outVertices + (numArcVertices * vertexStride);
  432. UINT8* otherSideNormals = outNormals + (numArcVertices * vertexStride);
  433. otherSideVertices = writeVector3(otherSideVertices, vertexStride, center);
  434. otherSideNormals = writeVector3(otherSideNormals, vertexStride, -visibleNormal);
  435. for (UINT32 i = 0; i < numArcVertices; i++)
  436. {
  437. otherSideVertices = writeVector3(otherSideVertices, vertexStride, *(Vector3*)outVertices);
  438. outVertices += vertexStride;
  439. outNormals = writeVector3(outNormals, vertexStride, visibleNormal);
  440. otherSideNormals = writeVector3(otherSideNormals, vertexStride, -visibleNormal);
  441. }
  442. UINT32 numTriangles = numArcVertices - 1;
  443. // If angle is negative the order of vertices is reversed so we need to reverse the indexes too
  444. UINT32 frontSideOffset = vertexOffset + (reverseOrder ? (numArcVertices + 1) : 0);
  445. UINT32 backSideOffset = vertexOffset + (!reverseOrder ? (numArcVertices + 1) : 0);
  446. for (UINT32 i = 0; i < numTriangles; i++)
  447. {
  448. outIndices[i * 6 + 0] = frontSideOffset + 0;
  449. outIndices[i * 6 + 1] = frontSideOffset + i + 1;
  450. outIndices[i * 6 + 2] = frontSideOffset + i;
  451. outIndices[i * 6 + 3] = backSideOffset + 0;
  452. outIndices[i * 6 + 4] = backSideOffset + i;
  453. outIndices[i * 6 + 5] = backSideOffset + i + 1;
  454. }
  455. }
  456. void ShapeMeshes3D::wireFrustum(const Vector3& position, float aspect, Degree FOV, float near, float far,
  457. UINT8* outVertices, UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset)
  458. {
  459. float fovTan = Math::tan(FOV * 0.5f);
  460. Vector3 nearPoint(0, 0, near);
  461. Vector3 nearWidth(near * fovTan * aspect, 0, 0);
  462. Vector3 nearHeight(0, (near * fovTan) / aspect, 0);
  463. Vector3 farPoint(0, 0, far);
  464. Vector3 farWidth(far * fovTan * aspect, 0, 0);
  465. Vector3 farHeight(0, (far * fovTan) / aspect, 0);
  466. Vector3 points[8] =
  467. {
  468. nearPoint + nearWidth + nearHeight,
  469. nearPoint - nearWidth + nearHeight,
  470. nearPoint - nearWidth - nearHeight,
  471. nearPoint + nearWidth - nearHeight,
  472. farPoint + farWidth + farHeight,
  473. farPoint - farWidth + farHeight,
  474. farPoint - farWidth - farHeight,
  475. farPoint + farWidth - farHeight
  476. };
  477. outVertices += vertexOffset * vertexStride;
  478. for (UINT32 i = 0; i < 8; i++)
  479. outVertices = writeVector3(outVertices, vertexStride, position + points[i]);
  480. outIndices += indexOffset;
  481. // Front
  482. outIndices[0] = vertexOffset + 0; outIndices[1] = vertexOffset + 1;
  483. outIndices[2] = vertexOffset + 1; outIndices[3] = vertexOffset + 2;
  484. outIndices[4] = vertexOffset + 2; outIndices[5] = vertexOffset + 3;
  485. outIndices[6] = vertexOffset + 3; outIndices[7] = vertexOffset + 0;
  486. // Center
  487. outIndices[8] = vertexOffset + 0; outIndices[9] = vertexOffset + 4;
  488. outIndices[10] = vertexOffset + 1; outIndices[11] = vertexOffset + 5;
  489. outIndices[12] = vertexOffset + 2; outIndices[13] = vertexOffset + 6;
  490. outIndices[14] = vertexOffset + 3; outIndices[15] = vertexOffset + 7;
  491. // Back
  492. outIndices[16] = vertexOffset + 4; outIndices[17] = vertexOffset + 5;
  493. outIndices[18] = vertexOffset + 5; outIndices[19] = vertexOffset + 6;
  494. outIndices[20] = vertexOffset + 6; outIndices[21] = vertexOffset + 7;
  495. outIndices[22] = vertexOffset + 7; outIndices[23] = vertexOffset + 4;
  496. }
  497. void ShapeMeshes3D::solidCone(const Vector3& base, const Vector3& normal, float height, float radius,
  498. UINT8* outVertices, UINT8* outNormals, UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset, UINT32 quality)
  499. {
  500. outVertices += vertexOffset * vertexStride;
  501. outIndices += indexOffset;
  502. if (outNormals != nullptr)
  503. outNormals += vertexOffset * vertexStride;
  504. // Generate base disc
  505. UINT32 numArcVertices = (quality + 1) * 4;
  506. generateArcVertices(base, normal, radius, Degree(0), Degree(360),
  507. numArcVertices + 1, outVertices, 0, vertexStride);
  508. outVertices += numArcVertices * vertexStride;
  509. outVertices = writeVector3(outVertices, vertexStride, base); // Write base vertex
  510. UINT32 baseIdx = numArcVertices;
  511. if (outNormals != nullptr)
  512. {
  513. UINT32 totalNumBaseVertices = numArcVertices + 1;
  514. for (UINT32 i = 0; i < totalNumBaseVertices; i++)
  515. outNormals = writeVector3(outNormals, vertexStride, -normal);
  516. }
  517. UINT32 numTriangles = numArcVertices;
  518. for (UINT32 i = 0; i < numTriangles - 1; i++)
  519. {
  520. outIndices[i * 3 + 0] = vertexOffset + baseIdx;
  521. outIndices[i * 3 + 1] = vertexOffset + i;
  522. outIndices[i * 3 + 2] = vertexOffset + i + 1;
  523. }
  524. {
  525. UINT32 i = numTriangles - 1;
  526. outIndices[i * 3 + 0] = vertexOffset + baseIdx;
  527. outIndices[i * 3 + 1] = vertexOffset + i;
  528. outIndices[i * 3 + 2] = vertexOffset + 0;
  529. }
  530. //// Generate cone
  531. // Base vertices
  532. generateArcVertices(base, normal, radius, Degree(0), Degree(360),
  533. numArcVertices + 1, outVertices, 0, vertexStride);
  534. Vector3 topVertex = base + normal * height;
  535. // Normals
  536. if (outNormals != nullptr)
  537. {
  538. UINT8* outNormalsBase = outNormals;
  539. UINT8* outNormalsTop = outNormals + numArcVertices * vertexStride;
  540. for (INT32 i = 0; i < (INT32)numArcVertices; i++)
  541. {
  542. int offsetA = i == 0 ? numArcVertices - 1 : i - 1;
  543. int offsetB = i;
  544. int offsetC = (i + 1) % numArcVertices;
  545. Vector3* a = (Vector3*)(outVertices + (offsetA * vertexStride));
  546. Vector3* b = (Vector3*)(outVertices + (offsetB * vertexStride));
  547. Vector3* c = (Vector3*)(outVertices + (offsetC * vertexStride));
  548. Vector3 toTop = topVertex - *b;
  549. Vector3 normalLeft = Vector3::cross(toTop, *a - *b);
  550. normalLeft.normalize();
  551. Vector3 normalRight = Vector3::cross(*c - *b, toTop);
  552. normalRight.normalize();
  553. Vector3 triNormal = Vector3::normalize(normalLeft + normalRight);
  554. outNormalsBase = writeVector3(outNormalsBase, vertexStride, triNormal);
  555. outNormalsTop = writeVector3(outNormalsTop, vertexStride, triNormal);
  556. }
  557. }
  558. // Top vertices (All same position, but need them separate because of different normals)
  559. outVertices += numArcVertices * vertexStride;
  560. for (UINT32 i = 0; i < numArcVertices; i++)
  561. outVertices = writeVector3(outVertices, vertexStride, topVertex);
  562. outIndices += numTriangles * 3;
  563. UINT32 curVertBaseOffset = vertexOffset + numArcVertices + 1;
  564. UINT32 curVertTopOffset = curVertBaseOffset + numArcVertices;
  565. for (UINT32 i = 0; i < numTriangles - 1; i++)
  566. {
  567. outIndices[i * 3 + 0] = curVertTopOffset + i;
  568. outIndices[i * 3 + 1] = curVertBaseOffset + i + 1;
  569. outIndices[i * 3 + 2] = curVertBaseOffset + i;
  570. }
  571. {
  572. UINT32 i = numTriangles - 1;
  573. outIndices[i * 3 + 0] = curVertTopOffset + i;
  574. outIndices[i * 3 + 1] = curVertBaseOffset + 0;
  575. outIndices[i * 3 + 2] = curVertBaseOffset + i;
  576. }
  577. }
  578. void ShapeMeshes3D::solidQuad(const Rect3& area, UINT8* outVertices, UINT8* outNormals, UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset)
  579. {
  580. outVertices += (vertexOffset * vertexStride);
  581. Vector3 topLeft = area.getCenter() - area.getAxisHorz() * area.getExtentHorz() + area.getAxisVert() * area.getExtentVertical();
  582. Vector3 topRight = area.getCenter() + area.getAxisHorz() * area.getExtentHorz() + area.getAxisVert() * area.getExtentVertical();
  583. Vector3 botRight = area.getCenter() + area.getAxisHorz() * area.getExtentHorz() - area.getAxisVert() * area.getExtentVertical();
  584. Vector3 botLeft = area.getCenter() - area.getAxisHorz() * area.getExtentHorz() - area.getAxisVert() * area.getExtentVertical();
  585. outVertices = writeVector3(outVertices, vertexStride, topLeft);
  586. outVertices = writeVector3(outVertices, vertexStride, topRight);
  587. outVertices = writeVector3(outVertices, vertexStride, botRight);
  588. outVertices = writeVector3(outVertices, vertexStride, botLeft);
  589. outVertices = writeVector3(outVertices, vertexStride, topLeft);
  590. outVertices = writeVector3(outVertices, vertexStride, topRight);
  591. outVertices = writeVector3(outVertices, vertexStride, botRight);
  592. outVertices = writeVector3(outVertices, vertexStride, botLeft);
  593. Vector3 normal = area.getAxisHorz().cross(area.getAxisVert());
  594. Vector3 reverseNormal = -normal;
  595. outNormals += (vertexOffset * vertexStride);
  596. outNormals = writeVector3(outNormals, vertexStride, normal);
  597. outNormals = writeVector3(outNormals, vertexStride, normal);
  598. outNormals = writeVector3(outNormals, vertexStride, normal);
  599. outNormals = writeVector3(outNormals, vertexStride, normal);
  600. outNormals = writeVector3(outNormals, vertexStride, reverseNormal);
  601. outNormals = writeVector3(outNormals, vertexStride, reverseNormal);
  602. outNormals = writeVector3(outNormals, vertexStride, reverseNormal);
  603. outNormals = writeVector3(outNormals, vertexStride, reverseNormal);
  604. outIndices += indexOffset;
  605. outIndices[0] = vertexOffset;
  606. outIndices[1] = vertexOffset + 1;
  607. outIndices[2] = vertexOffset + 2;
  608. outIndices[3] = vertexOffset;
  609. outIndices[4] = vertexOffset + 2;
  610. outIndices[5] = vertexOffset + 3;
  611. outIndices[6] = vertexOffset + 4;
  612. outIndices[7] = vertexOffset + 6;
  613. outIndices[8] = vertexOffset + 5;
  614. outIndices[9] = vertexOffset + 4;
  615. outIndices[10] = vertexOffset + 7;
  616. outIndices[11] = vertexOffset + 6;
  617. }
  618. Vector3 ShapeMeshes3D::calcCenter(UINT8* vertices, UINT32 numVertices, UINT32 vertexStride)
  619. {
  620. Vector3 center = Vector3::ZERO;
  621. for(UINT32 i = 0; i < numVertices; i++)
  622. {
  623. Vector3* curVert = (Vector3*)vertices;
  624. center += *curVert;
  625. vertices += vertexStride;
  626. }
  627. center /= (float)numVertices;
  628. return center;
  629. }
  630. void ShapeMeshes3D::pixelLine(const Vector3& a, const Vector3& b, UINT8* outVertices,
  631. UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset)
  632. {
  633. outVertices += (vertexOffset * vertexStride);
  634. Vector3* vertices = (Vector3*)outVertices;
  635. (*vertices) = a;
  636. vertices = (Vector3*)(outVertices + vertexStride);
  637. (*vertices) = b;
  638. outIndices += indexOffset;
  639. outIndices[0] = vertexOffset + 0;
  640. outIndices[1] = vertexOffset + 1;
  641. }
  642. void ShapeMeshes3D::antialiasedLine(const Vector3& a, const Vector3& b, const Vector3& up, float width, float borderWidth, const Color& color, UINT8* outVertices, UINT8* outColors,
  643. UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset)
  644. {
  645. Vector3 dir = b - a;
  646. dir.normalize();
  647. Vector3 right = dir.cross(up);
  648. right.normalize();
  649. Vector<Vector3> points(4);
  650. float r = width * 0.5f;
  651. dir = dir * r;
  652. right = right * r;
  653. Vector3 v0 = a - dir - right;
  654. Vector3 v1 = a - dir + right;
  655. Vector3 v2 = b + dir + right;
  656. Vector3 v3 = b + dir - right;
  657. points[0] = v0;
  658. points[1] = v1;
  659. points[2] = v2;
  660. points[3] = v3;
  661. antialiasedPolygon(points, up, borderWidth, color, outVertices, outColors, vertexOffset, vertexStride, outIndices, indexOffset);
  662. }
  663. void ShapeMeshes3D::pixelSolidPolygon(const Vector<Vector3>& points, UINT8* outVertices,
  664. UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset)
  665. {
  666. outVertices += (vertexOffset * vertexStride);
  667. for (auto& point : points)
  668. {
  669. Vector3* vertices = (Vector3*)outVertices;
  670. (*vertices) = point;
  671. outVertices += vertexStride;
  672. }
  673. outIndices += indexOffset;
  674. INT32 numPoints = (INT32)points.size();
  675. UINT32 idxCnt = 0;
  676. for (int i = 2; i < numPoints; i++)
  677. {
  678. outIndices[idxCnt++] = vertexOffset;
  679. outIndices[idxCnt++] = vertexOffset + i - 1;
  680. outIndices[idxCnt++] = vertexOffset + i;
  681. }
  682. }
  683. void ShapeMeshes3D::pixelWirePolygon(const Vector<Vector3>& points, UINT8* outVertices,
  684. UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset)
  685. {
  686. INT32 numPoints = (INT32)points.size();
  687. UINT32 curVertOffset = vertexOffset;
  688. UINT32 curIdxOffset = indexOffset;
  689. for (INT32 i = 0, j = numPoints - 1; i < numPoints; j = i++)
  690. {
  691. pixelLine(points[j], points[i], outVertices, curVertOffset, vertexStride, outIndices, curIdxOffset);
  692. curVertOffset += 2;
  693. curIdxOffset += 2;
  694. }
  695. }
  696. void ShapeMeshes3D::antialiasedPolygon(const Vector<Vector3>& points, const Vector3& up, float borderWidth, const Color& color, UINT8* outVertices, UINT8* outColors,
  697. UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset)
  698. {
  699. UINT32 numCoords = (UINT32)points.size();
  700. outVertices += vertexOffset * vertexStride;
  701. outColors += vertexOffset * vertexStride;
  702. Vector<Vector3> tempNormals(numCoords);
  703. for (UINT32 i = 0, j = numCoords - 1; i < numCoords; j = i++)
  704. {
  705. const Vector3& v0 = points[j];
  706. const Vector3& v1 = points[i];
  707. Vector3 dir = v1 - v0;
  708. Vector3 right = dir.cross(up);
  709. right.normalize();
  710. tempNormals[j] = right;
  711. // Also start populating the vertex array
  712. Vector3* vertices = (Vector3*)outVertices;
  713. *vertices = v1;
  714. UINT32* colors = (UINT32*)outColors;
  715. *colors = color.getAsRGBA();
  716. outVertices += vertexStride;
  717. outColors += vertexStride;
  718. }
  719. Color transparentColor = color;
  720. transparentColor.a = 0.0f;
  721. for (UINT32 i = 0, j = numCoords - 1; i < numCoords; j = i++)
  722. {
  723. const Vector3& n0 = tempNormals[j];
  724. const Vector3& n1 = tempNormals[i];
  725. Vector3 avgNrm = (n0 + n1) * 0.5f;
  726. float magSqrd = avgNrm.squaredLength();
  727. if (magSqrd > 0.000001f)
  728. {
  729. float scale = 1.0f / magSqrd;
  730. if (scale > 10.0f)
  731. scale = 10.0f;
  732. avgNrm = avgNrm * scale;
  733. }
  734. Vector3 tempCoord = points[i] + avgNrm * borderWidth;
  735. // Move it to the vertex array
  736. Vector3* vertices = (Vector3*)outVertices;
  737. *vertices = tempCoord;
  738. UINT32* colors = (UINT32*)outColors;
  739. *colors = transparentColor.getAsRGBA();
  740. outVertices += vertexStride;
  741. outColors += vertexStride;
  742. }
  743. // Populate index buffer
  744. outIndices += indexOffset;
  745. UINT32 idxCnt = 0;
  746. for (UINT32 i = 0, j = numCoords - 1; i < numCoords; j = i++)
  747. {
  748. outIndices[idxCnt++] = vertexOffset + i;
  749. outIndices[idxCnt++] = vertexOffset + j;
  750. outIndices[idxCnt++] = vertexOffset + numCoords + j;
  751. outIndices[idxCnt++] = vertexOffset + numCoords + j;
  752. outIndices[idxCnt++] = vertexOffset + numCoords + i;
  753. outIndices[idxCnt++] = vertexOffset + i;
  754. }
  755. for (UINT32 i = 2; i < numCoords; ++i)
  756. {
  757. outIndices[idxCnt++] = vertexOffset + 0;
  758. outIndices[idxCnt++] = vertexOffset + i - 1;
  759. outIndices[idxCnt++] = vertexOffset + i;
  760. }
  761. }
  762. UINT32 ShapeMeshes3D::subdivideTriangleOnSphere(const Vector3& center, float radius, UINT32 numLevels,
  763. const Vector3& a, const Vector3& b, const Vector3& c,
  764. UINT8* outVertices, UINT8* outNormals, UINT32 vertexOffset, UINT32 vertexStride)
  765. {
  766. outVertices += (vertexOffset * vertexStride);
  767. if (outNormals != nullptr)
  768. outNormals += (vertexOffset * vertexStride);
  769. UINT32 numVertices = 0;
  770. if (numLevels > 0)
  771. {
  772. Vector3 sub1 = Vector3::normalize((a + b) * 0.5f);
  773. Vector3 sub2 = Vector3::normalize((b + c) * 0.5f);
  774. Vector3 sub3 = Vector3::normalize((c + a) * 0.5f);
  775. numLevels--;
  776. numVertices += subdivideTriangleOnSphere(center, radius, numLevels, a, sub1, sub3, outVertices,
  777. outNormals, numVertices, vertexStride);
  778. numVertices += subdivideTriangleOnSphere(center, radius, numLevels, sub1, b, sub2, outVertices,
  779. outNormals, numVertices, vertexStride);
  780. numVertices += subdivideTriangleOnSphere(center, radius, numLevels, sub1, sub2, sub3, outVertices,
  781. outNormals, numVertices, vertexStride);
  782. numVertices += subdivideTriangleOnSphere(center, radius, numLevels, sub3, sub2, c, outVertices,
  783. outNormals, numVertices, vertexStride);
  784. }
  785. else
  786. {
  787. *((Vector3*)outVertices) = center + a * radius;
  788. outVertices += vertexStride;
  789. *((Vector3*)outVertices) = center + b * radius;
  790. outVertices += vertexStride;
  791. *((Vector3*)outVertices) = center + c * radius;
  792. outVertices += vertexStride;
  793. if (outNormals != nullptr)
  794. {
  795. *((Vector3*)outNormals) = a;
  796. outNormals += vertexStride;
  797. *((Vector3*)outNormals) = b;
  798. outNormals += vertexStride;
  799. *((Vector3*)outNormals) = c;
  800. outNormals += vertexStride;
  801. }
  802. numVertices += 3;
  803. }
  804. return numVertices;
  805. }
  806. void ShapeMeshes3D::generateArcVertices(const Vector3& center, const Vector3& up, float radius, Degree startAngle, Degree angleAmount, UINT32 numVertices,
  807. UINT8* outVertices, UINT32 vertexOffset, UINT32 vertexStride)
  808. {
  809. assert(numVertices >= 2);
  810. Quaternion alignWithStart = Quaternion(-Vector3::UNIT_Y, startAngle);
  811. Quaternion alignWithUp = Quaternion::getRotationFromTo(Vector3::UNIT_Y, up);
  812. Vector3 right = alignWithUp.rotate(alignWithStart.rotate(Vector3::UNIT_X));
  813. right.normalize();
  814. Quaternion increment(up, angleAmount / (float)(numVertices - 1));
  815. outVertices += vertexOffset * vertexStride;
  816. Vector3 curDirection = right * radius;
  817. for (UINT32 i = 0; i < numVertices; i++)
  818. {
  819. outVertices = writeVector3(outVertices, vertexStride, center + curDirection);
  820. curDirection = increment.rotate(curDirection);
  821. }
  822. }
  823. }