BsShapeMeshes3D.cpp 34 KB

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