BsDrawHelper.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993
  1. #include "BsDrawHelper.h"
  2. #include "BsMesh.h"
  3. #include "BsAABox.h"
  4. #include "BsSphere.h"
  5. #include "BsVertexDataDesc.h"
  6. #include "BsMeshHeap.h"
  7. #include "BsShapeMeshes3D.h"
  8. #include "BsTextData.h"
  9. #include "BsVector2.h"
  10. namespace BansheeEngine
  11. {
  12. const UINT32 DrawHelper::VERTEX_BUFFER_GROWTH = 4096;
  13. const UINT32 DrawHelper::INDEX_BUFFER_GROWTH = 4096 * 2;
  14. DrawHelper::DrawHelper()
  15. :mLayer(1)
  16. {
  17. mTransform = Matrix4::IDENTITY;
  18. mSolidVertexDesc = bs_shared_ptr_new<VertexDataDesc>();
  19. mSolidVertexDesc->addVertElem(VET_FLOAT3, VES_POSITION);
  20. mSolidVertexDesc->addVertElem(VET_FLOAT3, VES_NORMAL);
  21. mSolidVertexDesc->addVertElem(VET_COLOR, VES_COLOR);
  22. mWireVertexDesc = bs_shared_ptr_new<VertexDataDesc>();
  23. mWireVertexDesc->addVertElem(VET_FLOAT3, VES_POSITION);
  24. mWireVertexDesc->addVertElem(VET_COLOR, VES_COLOR);
  25. mTextVertexDesc = bs_shared_ptr_new<VertexDataDesc>();
  26. mTextVertexDesc->addVertElem(VET_FLOAT3, VES_POSITION);
  27. mTextVertexDesc->addVertElem(VET_FLOAT2, VES_TEXCOORD);
  28. mTextVertexDesc->addVertElem(VET_COLOR, VES_COLOR);
  29. mSolidMeshHeap = MeshHeap::create(VERTEX_BUFFER_GROWTH, INDEX_BUFFER_GROWTH, mSolidVertexDesc);
  30. mWireMeshHeap = MeshHeap::create(VERTEX_BUFFER_GROWTH, INDEX_BUFFER_GROWTH, mWireVertexDesc);
  31. mTextMeshHeap = MeshHeap::create(VERTEX_BUFFER_GROWTH, INDEX_BUFFER_GROWTH, mTextVertexDesc);
  32. }
  33. DrawHelper::~DrawHelper()
  34. {
  35. clearMeshes();
  36. }
  37. void DrawHelper::setColor(const Color& color)
  38. {
  39. mColor = color;
  40. }
  41. void DrawHelper::setTransform(const Matrix4& transform)
  42. {
  43. mTransform = transform;
  44. }
  45. void DrawHelper::setLayer(UINT64 layer)
  46. {
  47. mLayer = layer;
  48. }
  49. void DrawHelper::cube(const Vector3& position, const Vector3& extents)
  50. {
  51. mSolidCubeData.push_back(CubeData());
  52. CubeData& cubeData = mSolidCubeData.back();
  53. cubeData.position = position;
  54. cubeData.extents = extents;
  55. cubeData.color = mColor;
  56. cubeData.transform = mTransform;
  57. cubeData.layer = mLayer;
  58. cubeData.center = mTransform.multiplyAffine(position);
  59. }
  60. void DrawHelper::sphere(const Vector3& position, float radius, UINT32 quality)
  61. {
  62. mSolidSphereData.push_back(SphereData());
  63. SphereData& sphereData = mSolidSphereData.back();
  64. sphereData.position = position;
  65. sphereData.radius = radius;
  66. sphereData.quality = quality;
  67. sphereData.color = mColor;
  68. sphereData.transform = mTransform;
  69. sphereData.layer = mLayer;
  70. sphereData.center = mTransform.multiplyAffine(position);
  71. }
  72. void DrawHelper::wireCube(const Vector3& position, const Vector3& extents)
  73. {
  74. mWireCubeData.push_back(CubeData());
  75. CubeData& cubeData = mWireCubeData.back();
  76. cubeData.position = position;
  77. cubeData.extents = extents;
  78. cubeData.color = mColor;
  79. cubeData.transform = mTransform;
  80. cubeData.layer = mLayer;
  81. cubeData.center = mTransform.multiplyAffine(position);
  82. }
  83. void DrawHelper::wireSphere(const Vector3& position, float radius, UINT32 quality)
  84. {
  85. mWireSphereData.push_back(SphereData());
  86. SphereData& sphereData = mWireSphereData.back();
  87. sphereData.position = position;
  88. sphereData.radius = radius;
  89. sphereData.quality = quality;
  90. sphereData.color = mColor;
  91. sphereData.transform = mTransform;
  92. sphereData.layer = mLayer;
  93. sphereData.center = mTransform.multiplyAffine(position);
  94. }
  95. void DrawHelper::line(const Vector3& start, const Vector3& end)
  96. {
  97. mLineData.push_back(LineData());
  98. LineData& lineData = mLineData.back();
  99. lineData.start = start;
  100. lineData.end = end;
  101. lineData.color = mColor;
  102. lineData.transform = mTransform;
  103. lineData.layer = mLayer;
  104. lineData.center = mTransform.multiplyAffine((start + end) * 0.5f);
  105. }
  106. void DrawHelper::frustum(const Vector3& position, float aspect, Degree FOV, float near, float far)
  107. {
  108. mFrustumData.push_back(FrustumData());
  109. FrustumData& frustumData = mFrustumData.back();
  110. frustumData.position = position;
  111. frustumData.aspect = aspect;
  112. frustumData.FOV = FOV;
  113. frustumData.near = near;
  114. frustumData.far = far;
  115. frustumData.color = mColor;
  116. frustumData.transform = mTransform;
  117. frustumData.layer = mLayer;
  118. frustumData.center = mTransform.multiplyAffine(position);
  119. }
  120. void DrawHelper::cone(const Vector3& base, const Vector3& normal, float height, float radius, UINT32 quality)
  121. {
  122. mConeData.push_back(ConeData());
  123. ConeData& coneData = mConeData.back();
  124. coneData.base = base;
  125. coneData.normal = normal;
  126. coneData.height = height;
  127. coneData.radius = radius;
  128. coneData.quality = quality;
  129. coneData.color = mColor;
  130. coneData.transform = mTransform;
  131. coneData.layer = mLayer;
  132. coneData.center = mTransform.multiplyAffine(base + normal * height * 0.5f);
  133. }
  134. void DrawHelper::disc(const Vector3& position, const Vector3& normal, float radius, UINT32 quality)
  135. {
  136. mDiscData.push_back(DiscData());
  137. DiscData& discData = mDiscData.back();
  138. discData.position = position;
  139. discData.normal = normal;
  140. discData.radius = radius;
  141. discData.quality = quality;
  142. discData.color = mColor;
  143. discData.transform = mTransform;
  144. discData.layer = mLayer;
  145. discData.center = mTransform.multiplyAffine(position);
  146. }
  147. void DrawHelper::wireDisc(const Vector3& position, const Vector3& normal, float radius, UINT32 quality)
  148. {
  149. mWireDiscData.push_back(DiscData());
  150. DiscData& discData = mWireDiscData.back();
  151. discData.position = position;
  152. discData.normal = normal;
  153. discData.radius = radius;
  154. discData.quality = quality;
  155. discData.color = mColor;
  156. discData.transform = mTransform;
  157. discData.layer = mLayer;
  158. discData.center = mTransform.multiplyAffine(position);
  159. }
  160. void DrawHelper::arc(const Vector3& position, const Vector3& normal, float radius,
  161. Degree startAngle, Degree amountAngle, UINT32 quality)
  162. {
  163. mArcData.push_back(ArcData());
  164. ArcData& arcData = mArcData.back();
  165. arcData.position = position;
  166. arcData.normal = normal;
  167. arcData.radius = radius;
  168. arcData.startAngle = startAngle;
  169. arcData.amountAngle = amountAngle;
  170. arcData.quality = quality;
  171. arcData.color = mColor;
  172. arcData.transform = mTransform;
  173. arcData.layer = mLayer;
  174. arcData.center = mTransform.multiplyAffine(position);
  175. }
  176. void DrawHelper::wireArc(const Vector3& position, const Vector3& normal, float radius,
  177. Degree startAngle, Degree amountAngle, UINT32 quality)
  178. {
  179. mWireArcData.push_back(ArcData());
  180. ArcData& arcData = mWireArcData.back();
  181. arcData.position = position;
  182. arcData.normal = normal;
  183. arcData.radius = radius;
  184. arcData.startAngle = startAngle;
  185. arcData.amountAngle = amountAngle;
  186. arcData.quality = quality;
  187. arcData.color = mColor;
  188. arcData.transform = mTransform;
  189. arcData.layer = mLayer;
  190. arcData.center = mTransform.multiplyAffine(position);
  191. }
  192. void DrawHelper::rectangle(const Rect3& area)
  193. {
  194. mRect3Data.push_back(Rect3Data());
  195. Rect3Data& rectData = mRect3Data.back();
  196. rectData.area = area;
  197. rectData.color = mColor;
  198. rectData.transform = mTransform;
  199. rectData.layer = mLayer;
  200. rectData.center = mTransform.multiplyAffine(area.getCenter());
  201. }
  202. void DrawHelper::text(const Vector3& position, const WString& text, const HFont& font, UINT32 size)
  203. {
  204. if (!font.isLoaded() || text.empty())
  205. return;
  206. mText2DData.push_back(Text2DData());
  207. Text2DData& textData = mText2DData.back();
  208. textData.position = position;
  209. textData.color = mColor;
  210. textData.transform = mTransform;
  211. textData.layer = mLayer;
  212. textData.center = mTransform.multiplyAffine(position);
  213. textData.text = text;
  214. textData.font = font;
  215. textData.size = size;
  216. }
  217. void DrawHelper::clear()
  218. {
  219. mSolidCubeData.clear();
  220. mWireCubeData.clear();
  221. mSolidSphereData.clear();
  222. mWireSphereData.clear();
  223. mLineData.clear();
  224. mRect3Data.clear();
  225. mFrustumData.clear();
  226. mFrustumData.clear();
  227. mDiscData.clear();
  228. mWireDiscData.clear();
  229. mArcData.clear();
  230. mWireArcData.clear();
  231. mConeData.clear();
  232. mText2DData.clear();
  233. }
  234. void DrawHelper::buildMeshes(SortType sorting, const Vector3& reference, UINT64 layers)
  235. {
  236. clearMeshes();
  237. enum class ShapeType
  238. {
  239. Cube, Sphere, WireCube, WireSphere, Line, Frustum,
  240. Cone, Disc, WireDisc, Arc, WireArc, Rectangle, Text
  241. };
  242. struct RawData
  243. {
  244. ShapeType shapeType;
  245. MeshType meshType;
  246. UINT32 idx;
  247. UINT32 textIdx;
  248. float distance;
  249. UINT32 numVertices;
  250. UINT32 numIndices;
  251. };
  252. /************************************************************************/
  253. /* Sort everything according to specified sorting rule */
  254. /************************************************************************/
  255. UINT32 idx = 0;
  256. Vector<RawData> allShapes;
  257. UINT32 localIdx = 0;
  258. for (auto& shapeData : mSolidCubeData)
  259. {
  260. if ((shapeData.layer & layers) == 0)
  261. {
  262. localIdx++;
  263. continue;
  264. }
  265. allShapes.push_back(RawData());
  266. RawData& rawData = allShapes.back();
  267. rawData.idx = localIdx++;
  268. rawData.textIdx = 0;
  269. rawData.meshType = MeshType::Solid;
  270. rawData.shapeType = ShapeType::Cube;
  271. rawData.distance = shapeData.center.distance(reference);
  272. ShapeMeshes3D::getNumElementsAABox(rawData.numVertices, rawData.numIndices);
  273. }
  274. localIdx = 0;
  275. for (auto& shapeData : mSolidSphereData)
  276. {
  277. if ((shapeData.layer & layers) == 0)
  278. {
  279. localIdx++;
  280. continue;
  281. }
  282. allShapes.push_back(RawData());
  283. RawData& rawData = allShapes.back();
  284. rawData.idx = localIdx++;
  285. rawData.textIdx = 0;
  286. rawData.meshType = MeshType::Solid;
  287. rawData.shapeType = ShapeType::Sphere;
  288. rawData.distance = shapeData.center.distance(reference);
  289. ShapeMeshes3D::getNumElementsSphere(shapeData.quality,
  290. rawData.numVertices, rawData.numIndices);
  291. }
  292. localIdx = 0;
  293. for (auto& shapeData : mConeData)
  294. {
  295. if ((shapeData.layer & layers) == 0)
  296. {
  297. localIdx++;
  298. continue;
  299. }
  300. allShapes.push_back(RawData());
  301. RawData& rawData = allShapes.back();
  302. rawData.idx = localIdx++;
  303. rawData.textIdx = 0;
  304. rawData.meshType = MeshType::Solid;
  305. rawData.shapeType = ShapeType::Cone;
  306. rawData.distance = shapeData.center.distance(reference);
  307. ShapeMeshes3D::getNumElementsCone(shapeData.quality,
  308. rawData.numVertices, rawData.numIndices);
  309. }
  310. localIdx = 0;
  311. for (auto& shapeData : mDiscData)
  312. {
  313. if ((shapeData.layer & layers) == 0)
  314. {
  315. localIdx++;
  316. continue;
  317. }
  318. allShapes.push_back(RawData());
  319. RawData& rawData = allShapes.back();
  320. rawData.idx = localIdx++;
  321. rawData.textIdx = 0;
  322. rawData.meshType = MeshType::Solid;
  323. rawData.shapeType = ShapeType::Disc;
  324. rawData.distance = shapeData.center.distance(reference);
  325. ShapeMeshes3D::getNumElementsDisc(shapeData.quality,
  326. rawData.numVertices, rawData.numIndices);
  327. }
  328. localIdx = 0;
  329. for (auto& shapeData : mArcData)
  330. {
  331. if ((shapeData.layer & layers) == 0)
  332. {
  333. localIdx++;
  334. continue;
  335. }
  336. allShapes.push_back(RawData());
  337. RawData& rawData = allShapes.back();
  338. rawData.idx = localIdx++;
  339. rawData.textIdx = 0;
  340. rawData.meshType = MeshType::Solid;
  341. rawData.shapeType = ShapeType::Arc;
  342. rawData.distance = shapeData.center.distance(reference);
  343. ShapeMeshes3D::getNumElementsArc(shapeData.quality,
  344. rawData.numVertices, rawData.numIndices);
  345. }
  346. localIdx = 0;
  347. for (auto& shapeData : mRect3Data)
  348. {
  349. if ((shapeData.layer & layers) == 0)
  350. {
  351. localIdx++;
  352. continue;
  353. }
  354. allShapes.push_back(RawData());
  355. RawData& rawData = allShapes.back();
  356. rawData.idx = localIdx++;
  357. rawData.textIdx = 0;
  358. rawData.meshType = MeshType::Solid;
  359. rawData.shapeType = ShapeType::Rectangle;
  360. rawData.distance = shapeData.center.distance(reference);
  361. ShapeMeshes3D::getNumElementsQuad(rawData.numVertices, rawData.numIndices);
  362. }
  363. localIdx = 0;
  364. for (auto& shapeData : mWireCubeData)
  365. {
  366. if ((shapeData.layer & layers) == 0)
  367. {
  368. localIdx++;
  369. continue;
  370. }
  371. allShapes.push_back(RawData());
  372. RawData& rawData = allShapes.back();
  373. rawData.idx = localIdx++;
  374. rawData.textIdx = 0;
  375. rawData.meshType = MeshType::Wire;
  376. rawData.shapeType = ShapeType::WireCube;
  377. rawData.distance = shapeData.center.distance(reference);
  378. ShapeMeshes3D::getNumElementsWireAABox(rawData.numVertices, rawData.numIndices);
  379. }
  380. localIdx = 0;
  381. for (auto& shapeData : mWireSphereData)
  382. {
  383. if ((shapeData.layer & layers) == 0)
  384. {
  385. localIdx++;
  386. continue;
  387. }
  388. allShapes.push_back(RawData());
  389. RawData& rawData = allShapes.back();
  390. rawData.idx = localIdx++;
  391. rawData.textIdx = 0;
  392. rawData.meshType = MeshType::Wire;
  393. rawData.shapeType = ShapeType::WireSphere;
  394. rawData.distance = shapeData.center.distance(reference);
  395. ShapeMeshes3D::getNumElementsWireSphere(shapeData.quality,
  396. rawData.numVertices, rawData.numIndices);
  397. }
  398. localIdx = 0;
  399. for (auto& shapeData : mLineData)
  400. {
  401. if ((shapeData.layer & layers) == 0)
  402. {
  403. localIdx++;
  404. continue;
  405. }
  406. allShapes.push_back(RawData());
  407. RawData& rawData = allShapes.back();
  408. rawData.idx = localIdx++;
  409. rawData.textIdx = 0;
  410. rawData.meshType = MeshType::Wire;
  411. rawData.shapeType = ShapeType::Line;
  412. rawData.distance = shapeData.center.distance(reference);
  413. rawData.numVertices = 2;
  414. rawData.numIndices = 2;
  415. }
  416. localIdx = 0;
  417. for (auto& shapeData : mFrustumData)
  418. {
  419. if ((shapeData.layer & layers) == 0)
  420. {
  421. localIdx++;
  422. continue;
  423. }
  424. allShapes.push_back(RawData());
  425. RawData& rawData = allShapes.back();
  426. rawData.idx = localIdx++;
  427. rawData.textIdx = 0;
  428. rawData.meshType = MeshType::Wire;
  429. rawData.shapeType = ShapeType::Frustum;
  430. rawData.distance = shapeData.center.distance(reference);
  431. ShapeMeshes3D::getNumElementsFrustum(rawData.numVertices, rawData.numIndices);
  432. }
  433. localIdx = 0;
  434. for (auto& shapeData : mWireDiscData)
  435. {
  436. if ((shapeData.layer & layers) == 0)
  437. {
  438. localIdx++;
  439. continue;
  440. }
  441. allShapes.push_back(RawData());
  442. RawData& rawData = allShapes.back();
  443. rawData.idx = localIdx++;
  444. rawData.textIdx = 0;
  445. rawData.meshType = MeshType::Wire;
  446. rawData.shapeType = ShapeType::WireDisc;
  447. rawData.distance = shapeData.center.distance(reference);
  448. ShapeMeshes3D::getNumElementsWireDisc(shapeData.quality,
  449. rawData.numVertices, rawData.numIndices);
  450. }
  451. localIdx = 0;
  452. for (auto& shapeData : mWireArcData)
  453. {
  454. if ((shapeData.layer & layers) == 0)
  455. {
  456. localIdx++;
  457. continue;
  458. }
  459. allShapes.push_back(RawData());
  460. RawData& rawData = allShapes.back();
  461. rawData.idx = localIdx++;
  462. rawData.textIdx = 0;
  463. rawData.meshType = MeshType::Wire;
  464. rawData.shapeType = ShapeType::WireArc;
  465. rawData.distance = shapeData.center.distance(reference);
  466. ShapeMeshes3D::getNumElementsWireArc(shapeData.quality,
  467. rawData.numVertices, rawData.numIndices);
  468. }
  469. struct TextRenderData
  470. {
  471. UINT32 page;
  472. SPtr<TextData<>> textData;
  473. };
  474. UnorderedMap<UINT32, TextRenderData> textRenderData;
  475. UINT32 textIdx = 0;
  476. localIdx = 0;
  477. for (auto& shapeData : mText2DData)
  478. {
  479. if ((shapeData.layer & layers) == 0)
  480. {
  481. localIdx++;
  482. continue;
  483. }
  484. SPtr<TextData<>> textData = bs_shared_ptr_new<TextData<>>(shapeData.text, shapeData.font, shapeData.size);
  485. UINT32 numPages = textData->getNumPages();
  486. for (UINT32 j = 0; j < numPages; j++)
  487. {
  488. UINT32 numQuads = textData->getNumQuadsForPage(j);
  489. allShapes.push_back(RawData());
  490. RawData& rawData = allShapes.back();
  491. rawData.idx = localIdx;
  492. rawData.textIdx = textIdx;
  493. rawData.meshType = MeshType::Text;
  494. rawData.shapeType = ShapeType::Text;
  495. rawData.distance = shapeData.center.distance(reference);
  496. rawData.numVertices = numQuads * 4;
  497. rawData.numIndices = numQuads * 6;
  498. TextRenderData& renderData = textRenderData[textIdx];
  499. renderData.page = j;
  500. renderData.textData = textData;
  501. textIdx++;
  502. idx++;
  503. }
  504. localIdx++;
  505. }
  506. if (sorting == SortType::FrontToBack)
  507. {
  508. std::sort(begin(allShapes), end(allShapes),
  509. [&](const RawData& x, const RawData& y)
  510. {
  511. return x.distance < y.distance;
  512. });
  513. }
  514. else if (sorting == SortType::BackToFront)
  515. {
  516. std::sort(begin(allShapes), end(allShapes),
  517. [&](const RawData& x, const RawData& y)
  518. {
  519. return y.distance < x.distance;
  520. });
  521. }
  522. /************************************************************************/
  523. /* Create batches */
  524. /************************************************************************/
  525. struct Batch
  526. {
  527. MeshType type;
  528. HTexture texture;
  529. UINT32 startIdx;
  530. UINT32 endIdx;
  531. UINT32 numVertices;
  532. UINT32 numIndices;
  533. };
  534. UINT32 numShapes = (UINT32)allShapes.size();
  535. Vector<Batch> batches;
  536. if (numShapes > 0)
  537. {
  538. batches.push_back(Batch());
  539. {
  540. Batch& currentBatch = batches.back();
  541. currentBatch.startIdx = 0;
  542. currentBatch.type = allShapes[0].meshType;
  543. currentBatch.numVertices = allShapes[0].numVertices;
  544. currentBatch.numIndices = allShapes[0].numIndices;
  545. if (allShapes[0].meshType == MeshType::Text)
  546. {
  547. TextRenderData& renderData = textRenderData[allShapes[0].textIdx];
  548. currentBatch.texture = renderData.textData->getTextureForPage(renderData.page);
  549. }
  550. }
  551. for (UINT32 i = 1; i < numShapes; i++)
  552. {
  553. Batch& currentBatch = batches.back();
  554. HTexture texture;
  555. bool startNewBatch = false;
  556. if(allShapes[i].meshType != currentBatch.type)
  557. {
  558. startNewBatch = true;
  559. }
  560. else
  561. {
  562. if(allShapes[i].meshType == MeshType::Text)
  563. {
  564. TextRenderData& renderData = textRenderData[allShapes[i].textIdx];
  565. texture = renderData.textData->getTextureForPage(renderData.page);
  566. if (texture != currentBatch.texture)
  567. startNewBatch = true;
  568. }
  569. }
  570. if (startNewBatch)
  571. {
  572. currentBatch.endIdx = i - 1;
  573. batches.push_back(Batch());
  574. Batch& newBatch = batches.back();
  575. newBatch.startIdx = i;
  576. newBatch.type = allShapes[i].meshType;
  577. newBatch.numVertices = allShapes[i].numVertices;
  578. newBatch.numIndices = allShapes[i].numIndices;
  579. newBatch.texture = texture;
  580. }
  581. else
  582. {
  583. currentBatch.endIdx = i;
  584. currentBatch.numVertices += allShapes[i].numVertices;
  585. currentBatch.numIndices += allShapes[i].numIndices;
  586. }
  587. }
  588. {
  589. Batch& currentBatch = batches.back();
  590. currentBatch.endIdx = numShapes - 1;
  591. }
  592. }
  593. /************************************************************************/
  594. /* Generate geometry for each batch */
  595. /************************************************************************/
  596. for (auto& batch : batches)
  597. {
  598. if (batch.type == MeshType::Solid)
  599. {
  600. MeshDataPtr meshData = bs_shared_ptr_new<MeshData>(batch.numVertices, batch.numIndices, mSolidVertexDesc);
  601. UINT32 curVertexOffset = 0;
  602. UINT32 curIndexOffet = 0;
  603. auto positionIter = meshData->getVec3DataIter(VES_POSITION);
  604. auto normalIter = meshData->getVec3DataIter(VES_NORMAL);
  605. auto colorIter = meshData->getDWORDDataIter(VES_COLOR);
  606. for (UINT32 i = batch.startIdx; i <= batch.endIdx; i++)
  607. {
  608. RawData& shapeData = allShapes[i];
  609. Matrix4* transform = nullptr;
  610. RGBA color = 0;
  611. switch (shapeData.shapeType)
  612. {
  613. case ShapeType::Cube:
  614. {
  615. CubeData& cubeData = mSolidCubeData[shapeData.idx];
  616. AABox box(cubeData.position - cubeData.extents, cubeData.position + cubeData.extents);
  617. ShapeMeshes3D::solidAABox(box, meshData, curVertexOffset, curIndexOffet);
  618. transform = &cubeData.transform;
  619. color = cubeData.color.getAsRGBA();
  620. }
  621. break;
  622. case ShapeType::Sphere:
  623. {
  624. SphereData& sphereData = mSolidSphereData[shapeData.idx];
  625. Sphere sphere(sphereData.position, sphereData.radius);
  626. ShapeMeshes3D::solidSphere(sphere, meshData, curVertexOffset, curIndexOffet, sphereData.quality);
  627. transform = &sphereData.transform;
  628. color = sphereData.color.getAsRGBA();
  629. }
  630. break;
  631. case ShapeType::Cone:
  632. {
  633. ConeData& coneData = mConeData[shapeData.idx];
  634. ShapeMeshes3D::solidCone(coneData.base, coneData.normal, coneData.height, coneData.radius,
  635. meshData, curVertexOffset, curIndexOffet, coneData.quality);
  636. transform = &coneData.transform;
  637. color = coneData.color.getAsRGBA();
  638. }
  639. break;
  640. case ShapeType::Disc:
  641. {
  642. DiscData& discData = mDiscData[shapeData.idx];
  643. ShapeMeshes3D::solidDisc(discData.position, discData.radius, discData.normal,
  644. meshData, curVertexOffset, curIndexOffet, discData.quality);
  645. transform = &discData.transform;
  646. color = discData.color.getAsRGBA();
  647. }
  648. break;
  649. case ShapeType::Arc:
  650. {
  651. ArcData& arcData = mArcData[shapeData.idx];
  652. ShapeMeshes3D::solidArc(arcData.position, arcData.radius, arcData.normal,
  653. arcData.startAngle, arcData.amountAngle, meshData, curVertexOffset, curIndexOffet, arcData.quality);
  654. transform = &arcData.transform;
  655. color = arcData.color.getAsRGBA();
  656. }
  657. break;
  658. case ShapeType::Rectangle:
  659. {
  660. Rect3Data rectData = mRect3Data[shapeData.idx];
  661. ShapeMeshes3D::solidQuad(rectData.area, meshData, curVertexOffset, curIndexOffet);
  662. transform = &rectData.transform;
  663. color = rectData.color.getAsRGBA();
  664. }
  665. break;
  666. }
  667. Matrix4 transformIT = transform->inverseAffine().transpose();
  668. for (UINT32 i = 0; i < shapeData.numVertices; i++)
  669. {
  670. Vector3 worldPos = transform->multiplyAffine(positionIter.getValue());
  671. Vector3 worldNormal = transformIT.multiplyAffine(normalIter.getValue());
  672. positionIter.addValue(worldPos);
  673. normalIter.addValue(worldNormal);
  674. colorIter.addValue(color);
  675. }
  676. curVertexOffset += shapeData.numVertices;
  677. curIndexOffet += shapeData.numIndices;
  678. }
  679. mMeshes.push_back(ShapeMeshData());
  680. ShapeMeshData& newMesh = mMeshes.back();
  681. newMesh.mesh = mSolidMeshHeap->alloc(meshData, DOT_TRIANGLE_LIST);
  682. newMesh.type = MeshType::Solid;
  683. }
  684. else if(batch.type == MeshType::Wire)
  685. {
  686. MeshDataPtr meshData = bs_shared_ptr_new<MeshData>(batch.numVertices,
  687. batch.numIndices, mWireVertexDesc);
  688. UINT32 curVertexOffset = 0;
  689. UINT32 curIndexOffet = 0;
  690. auto positionIter = meshData->getVec3DataIter(VES_POSITION);
  691. auto colorIter = meshData->getDWORDDataIter(VES_COLOR);
  692. for (UINT32 i = batch.startIdx; i <= batch.endIdx; i++)
  693. {
  694. RawData& shapeData = allShapes[i];
  695. Matrix4* transform = nullptr;
  696. RGBA color = 0;
  697. switch (shapeData.shapeType)
  698. {
  699. case ShapeType::WireCube:
  700. {
  701. CubeData& cubeData = mWireCubeData[shapeData.idx];
  702. AABox box(cubeData.position - cubeData.extents, cubeData.position + cubeData.extents);
  703. ShapeMeshes3D::wireAABox(box, meshData, curVertexOffset, curIndexOffet);
  704. transform = &cubeData.transform;
  705. color = cubeData.color.getAsRGBA();
  706. }
  707. break;
  708. case ShapeType::WireSphere:
  709. {
  710. SphereData& sphereData = mWireSphereData[shapeData.idx];
  711. Sphere sphere(sphereData.position, sphereData.radius);
  712. ShapeMeshes3D::wireSphere(sphere, meshData, curVertexOffset, curIndexOffet, sphereData.quality);
  713. transform = &sphereData.transform;
  714. color = sphereData.color.getAsRGBA();
  715. }
  716. break;
  717. case ShapeType::Line:
  718. {
  719. LineData& lineData = mLineData[shapeData.idx];
  720. ShapeMeshes3D::pixelLine(lineData.start, lineData.end, meshData, curVertexOffset, curIndexOffet);
  721. transform = &lineData.transform;
  722. color = lineData.color.getAsRGBA();
  723. }
  724. break;
  725. case ShapeType::Frustum:
  726. {
  727. FrustumData& frustumData = mFrustumData[shapeData.idx];
  728. ShapeMeshes3D::wireFrustum(frustumData.position, frustumData.aspect, frustumData.FOV, frustumData.near,
  729. frustumData.far, meshData, curVertexOffset, curIndexOffet);
  730. transform = &frustumData.transform;
  731. color = frustumData.color.getAsRGBA();
  732. }
  733. break;
  734. case ShapeType::WireDisc:
  735. {
  736. DiscData& discData = mWireDiscData[shapeData.idx];
  737. ShapeMeshes3D::wireDisc(discData.position, discData.radius, discData.normal,
  738. meshData, curVertexOffset, curIndexOffet, discData.quality);
  739. transform = &discData.transform;
  740. color = discData.color.getAsRGBA();
  741. }
  742. break;
  743. case ShapeType::WireArc:
  744. {
  745. ArcData& arcData = mWireArcData[shapeData.idx];
  746. ShapeMeshes3D::wireArc(arcData.position, arcData.radius, arcData.normal,
  747. arcData.startAngle, arcData.amountAngle, meshData, curVertexOffset, curIndexOffet, arcData.quality);
  748. transform = &arcData.transform;
  749. color = arcData.color.getAsRGBA();
  750. }
  751. break;
  752. }
  753. for (UINT32 i = 0; i < shapeData.numVertices; i++)
  754. {
  755. Vector3 worldPos = transform->multiplyAffine(positionIter.getValue());
  756. positionIter.addValue(worldPos);
  757. colorIter.addValue(color);
  758. }
  759. curVertexOffset += shapeData.numVertices;
  760. curIndexOffet += shapeData.numIndices;
  761. }
  762. mMeshes.push_back(ShapeMeshData());
  763. ShapeMeshData& newMesh = mMeshes.back();
  764. newMesh.mesh = mWireMeshHeap->alloc(meshData, DOT_LINE_LIST);
  765. newMesh.type = MeshType::Wire;
  766. }
  767. else // Text
  768. {
  769. MeshDataPtr meshData = bs_shared_ptr_new<MeshData>(batch.numVertices,
  770. batch.numIndices, mTextVertexDesc);
  771. UINT32 curVertexOffset = 0;
  772. UINT32 curIndexOffet = 0;
  773. auto positionIter = meshData->getVec3DataIter(VES_POSITION);
  774. auto uvIter = meshData->getVec2DataIter(VES_TEXCOORD);
  775. auto colorIter = meshData->getDWORDDataIter(VES_COLOR);
  776. for (UINT32 i = batch.startIdx; i <= batch.endIdx; i++)
  777. {
  778. RawData& shapeData = allShapes[i];
  779. Text2DData& text2DData = mText2DData[shapeData.idx];
  780. TextRenderData& renderData = textRenderData[shapeData.textIdx];
  781. UINT32 numQuads = renderData.textData->getNumQuadsForPage(renderData.page);
  782. UINT32* indices = meshData->getIndices32();
  783. // Note: Need temporary buffers because TextLine doesn't support arbitrary vertex stride. Eventually
  784. // that should be supported (should be almost trivial to implement)
  785. Vector2* tempVertices = bs_stack_alloc<Vector2>(shapeData.numVertices);
  786. Vector2* tempUVs = bs_stack_alloc<Vector2>(shapeData.numVertices);
  787. UINT32 numLines = renderData.textData->getNumLines();
  788. UINT32 quadOffset = 0;
  789. for (UINT32 j = 0; j < numLines; j++)
  790. {
  791. const TextDataBase::TextLine& line = renderData.textData->getLine(j);
  792. UINT32 writtenQuads = line.fillBuffer(renderData.page, tempVertices, tempUVs, indices, quadOffset, numQuads);
  793. quadOffset += writtenQuads;
  794. }
  795. for (UINT32 j = 0; j < shapeData.numVertices; j++)
  796. {
  797. Vector3 localPos(tempVertices[j].x, tempVertices[j].y, 0.0f);
  798. Vector3 worldPos = text2DData.transform.multiplyAffine(localPos);
  799. positionIter.addValue(worldPos);
  800. uvIter.addValue(tempUVs[j]);
  801. colorIter.addValue(text2DData.color.getAsRGBA());
  802. }
  803. bs_stack_free(tempVertices);
  804. bs_stack_free(tempUVs);
  805. curVertexOffset += shapeData.numVertices;
  806. curIndexOffet += shapeData.numIndices;
  807. }
  808. mMeshes.push_back(ShapeMeshData());
  809. ShapeMeshData& newMesh = mMeshes.back();
  810. newMesh.mesh = mTextMeshHeap->alloc(meshData, DOT_TRIANGLE_LIST);
  811. newMesh.type = MeshType::Text;
  812. }
  813. }
  814. }
  815. void DrawHelper::clearMeshes()
  816. {
  817. for (auto meshData : mMeshes)
  818. {
  819. if (meshData.type == MeshType::Solid)
  820. mSolidMeshHeap->dealloc(meshData.mesh);
  821. else if (meshData.type == MeshType::Wire)
  822. mWireMeshHeap->dealloc(meshData.mesh);
  823. else // Text
  824. mTextMeshHeap->dealloc(meshData.mesh);
  825. }
  826. mMeshes.clear();
  827. }
  828. }