BsDrawHelper2D.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. #include "BsDrawHelper2D.h"
  2. #include "CmFRect.h"
  3. #include "CmMesh.h"
  4. #include "CmTime.h"
  5. #include "CmVector2.h"
  6. #include "CmMaterial.h"
  7. #include "CmPass.h"
  8. #include "CmApplication.h"
  9. #include "CmRenderQueue.h"
  10. #include "BsCamera.h"
  11. #include "CmCoreThreadAccessor.h"
  12. #include "BsBuiltinMaterialManager.h"
  13. using namespace CamelotFramework;
  14. namespace BansheeEngine
  15. {
  16. DrawHelper2D::DrawHelper2D()
  17. {
  18. mMaterial2DClipSpace = BuiltinMaterialManager::instance().createDebugDraw2DClipSpaceMaterial();
  19. }
  20. void DrawHelper2D::quad(const CM::FRect& area, const MeshDataPtr& meshData, CM::UINT32 vertexOffset, CM::UINT32 indexOffset)
  21. {
  22. UINT32* indexData = meshData->getIndices32();
  23. UINT8* positionData = meshData->getElementData(VES_POSITION);
  24. assert((vertexOffset + 4) <= meshData->getNumVertices());
  25. assert((indexOffset + 6) <= meshData->getNumIndices());
  26. Vector<Vector2>::type points;
  27. points.push_back(Vector2(area.x, area.y));
  28. points.push_back(Vector2(area.x + area.width, area.y));
  29. points.push_back(Vector2(area.x + area.width, area.y + area.height));
  30. points.push_back(Vector2(area.x, area.y + area.height));
  31. polygonFill_Pixel(points, positionData, vertexOffset, meshData->getVertexStride(), indexData, indexOffset);
  32. }
  33. void DrawHelper2D::line_Pixel(const Vector2& a, const Vector2& b, const CM::Color& color, const CM::MeshDataPtr& meshData, CM::UINT32 vertexOffset, CM::UINT32 indexOffset)
  34. {
  35. DrawHelperTemplate<Vector2>::line_Pixel(a, b, color, meshData, vertexOffset, indexOffset);
  36. }
  37. void DrawHelper2D::line_AA(const Vector2& a, const Vector2& b, float width, float borderWidth, const CM::Color& color, const CM::MeshDataPtr& meshData, CM::UINT32 vertexOffset, CM::UINT32 indexOffset)
  38. {
  39. DrawHelperTemplate<Vector2>::line_AA(a, b, width, borderWidth, color, meshData, vertexOffset, indexOffset);
  40. }
  41. void DrawHelper2D::lineList_Pixel(const CM::Vector<Vector2>::type& linePoints, const CM::Color& color, const CM::MeshDataPtr& meshData, CM::UINT32 vertexOffset, CM::UINT32 indexOffset)
  42. {
  43. DrawHelperTemplate<Vector2>::lineList_Pixel(linePoints, color, meshData, vertexOffset, indexOffset);
  44. }
  45. void DrawHelper2D::lineList_AA(const CM::Vector<Vector2>::type& linePoints, float width, float borderWidth, const CM::Color& color, const CM::MeshDataPtr& meshData, CM::UINT32 vertexOffset, CM::UINT32 indexOffset)
  46. {
  47. DrawHelperTemplate<Vector2>::lineList_AA(linePoints, width, borderWidth, color, meshData, vertexOffset, indexOffset);
  48. }
  49. /************************************************************************/
  50. /* 2D - DRAW */
  51. /************************************************************************/
  52. void DrawHelper2D::drawQuad(const HCamera& camera, const CM::FRect& area, const Color& color, DebugDrawCoordType coordType, float timeout)
  53. {
  54. const Viewport* viewport = camera->getViewport().get();
  55. Vector<DebugDrawCommand>::type& commands = mCommandsPerViewport[viewport];
  56. commands.push_back(DebugDrawCommand());
  57. DebugDrawCommand& dbgCmd = commands.back();
  58. dbgCmd.endTime = gTime().getTime() + timeout;
  59. MeshDataPtr meshData = cm_shared_ptr<MeshData, ScratchAlloc>(4);
  60. meshData->beginDesc();
  61. meshData->addSubMesh(6);
  62. meshData->addVertElem(VET_FLOAT2, VES_POSITION);
  63. meshData->addVertElem(VET_COLOR, VES_COLOR);
  64. meshData->endDesc();
  65. FRect actualArea = area;
  66. if(coordType == DebugDrawCoordType::Normalized)
  67. actualArea = normalizedCoordToClipSpace(area);
  68. quad(actualArea, meshData, 0, 0);
  69. UINT32 vertexStride = meshData->getVertexStride();
  70. UINT8* colorData = meshData->getElementData(VES_COLOR);
  71. UINT32* colors = (UINT32*)colorData;
  72. (*colors) = color.getAsRGBA();
  73. colors = (UINT32*)(colorData + vertexStride);
  74. (*colors) = color.getAsRGBA();
  75. colors = (UINT32*)(colorData + vertexStride * 2);
  76. (*colors) = color.getAsRGBA();
  77. colors = (UINT32*)(colorData + vertexStride * 3);
  78. (*colors) = color.getAsRGBA();
  79. HMesh mesh = Mesh::create();
  80. gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, meshData);
  81. dbgCmd.mesh = mesh;
  82. dbgCmd.worldCenter = Vector3::ZERO;
  83. if(coordType == DebugDrawCoordType::Normalized)
  84. {
  85. dbgCmd.type = DebugDrawType::ClipSpace;
  86. dbgCmd.matInfo2DClipSpace = mMaterial2DClipSpace;
  87. }
  88. else
  89. {
  90. dbgCmd.type = DebugDrawType::ScreenSpace;
  91. dbgCmd.matInfo2DScreenSpace = BuiltinMaterialManager::instance().createDebugDraw2DScreenSpaceMaterial();
  92. }
  93. }
  94. void DrawHelper2D::drawLine_Pixel(const HCamera& camera, const Vector2& a, const Vector2& b, const Color& color, DebugDrawCoordType coordType, float timeout)
  95. {
  96. const Viewport* viewport = camera->getViewport().get();
  97. Vector<DebugDrawCommand>::type& commands = mCommandsPerViewport[viewport];
  98. commands.push_back(DebugDrawCommand());
  99. DebugDrawCommand& dbgCmd = commands.back();
  100. dbgCmd.endTime = gTime().getTime() + timeout;
  101. MeshDataPtr meshData = cm_shared_ptr<MeshData, ScratchAlloc>(2);
  102. meshData->beginDesc();
  103. meshData->addSubMesh(2, 0, DOT_LINE_LIST);
  104. meshData->addVertElem(VET_FLOAT2, VES_POSITION);
  105. meshData->addVertElem(VET_COLOR, VES_COLOR);
  106. meshData->endDesc();
  107. Vector2 actualA = a;
  108. Vector2 actualB = b;
  109. if(coordType == DebugDrawCoordType::Normalized)
  110. {
  111. actualA = normalizedCoordToClipSpace(a);
  112. actualB = normalizedCoordToClipSpace(b);
  113. }
  114. line_Pixel(actualA, actualB, color, meshData, 0, 0);
  115. HMesh mesh = Mesh::create();
  116. gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, meshData);
  117. dbgCmd.mesh = mesh;
  118. dbgCmd.worldCenter = Vector3::ZERO;
  119. if(coordType == DebugDrawCoordType::Normalized)
  120. {
  121. dbgCmd.type = DebugDrawType::ClipSpace;
  122. dbgCmd.matInfo2DClipSpace = mMaterial2DClipSpace;
  123. }
  124. else
  125. {
  126. dbgCmd.type = DebugDrawType::ScreenSpace;
  127. dbgCmd.matInfo2DScreenSpace = BuiltinMaterialManager::instance().createDebugDraw2DScreenSpaceMaterial();
  128. }
  129. }
  130. void DrawHelper2D::drawLine_AA(const HCamera& camera, const Vector2& a, const Vector2& b, float width, float borderWidth, const Color& color, DebugDrawCoordType coordType, float timeout)
  131. {
  132. const Viewport* viewport = camera->getViewport().get();
  133. Vector<DebugDrawCommand>::type& commands = mCommandsPerViewport[viewport];
  134. commands.push_back(DebugDrawCommand());
  135. DebugDrawCommand& dbgCmd = commands.back();
  136. dbgCmd.endTime = gTime().getTime() + timeout;
  137. MeshDataPtr meshData = cm_shared_ptr<MeshData, ScratchAlloc>(8);
  138. meshData->beginDesc();
  139. meshData->addSubMesh(30, 0, DOT_TRIANGLE_LIST);
  140. meshData->addVertElem(VET_FLOAT2, VES_POSITION);
  141. meshData->addVertElem(VET_COLOR, VES_COLOR);
  142. meshData->endDesc();
  143. Vector2 actualA = a;
  144. Vector2 actualB = b;
  145. if(coordType == DebugDrawCoordType::Normalized)
  146. {
  147. actualA = normalizedCoordToClipSpace(a);
  148. actualB = normalizedCoordToClipSpace(b);
  149. }
  150. line_AA(actualA, actualB, width, borderWidth, color, meshData, 0, 0);
  151. HMesh mesh = Mesh::create();
  152. gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, meshData);
  153. dbgCmd.mesh = mesh;
  154. dbgCmd.worldCenter = Vector3::ZERO;
  155. if(coordType == DebugDrawCoordType::Normalized)
  156. {
  157. dbgCmd.type = DebugDrawType::ClipSpace;
  158. dbgCmd.matInfo2DClipSpace = mMaterial2DClipSpace;
  159. }
  160. else
  161. {
  162. dbgCmd.type = DebugDrawType::ScreenSpace;
  163. dbgCmd.matInfo2DScreenSpace = BuiltinMaterialManager::instance().createDebugDraw2DScreenSpaceMaterial();
  164. }
  165. }
  166. void DrawHelper2D::drawLineList_Pixel(const HCamera& camera, const Vector<Vector2>::type& linePoints, const Color& color,
  167. DebugDrawCoordType coordType, float timeout)
  168. {
  169. const Viewport* viewport = camera->getViewport().get();
  170. Vector<DebugDrawCommand>::type& commands = mCommandsPerViewport[viewport];
  171. commands.push_back(DebugDrawCommand());
  172. DebugDrawCommand& dbgCmd = commands.back();
  173. dbgCmd.endTime = gTime().getTime() + timeout;
  174. MeshDataPtr meshData = cm_shared_ptr<MeshData, ScratchAlloc>((UINT32)(linePoints.size() * 2));
  175. meshData->beginDesc();
  176. meshData->addSubMesh((UINT32)(linePoints.size() * 2), 0, DOT_LINE_LIST);
  177. meshData->addVertElem(VET_FLOAT2, VES_POSITION);
  178. meshData->addVertElem(VET_COLOR, VES_COLOR);
  179. meshData->endDesc();
  180. if(coordType == DebugDrawCoordType::Normalized)
  181. {
  182. Vector<Vector2>::type points;
  183. UINT32 numPoints = (UINT32)linePoints.size();
  184. for(UINT32 i = 0; i < numPoints; i++)
  185. points.push_back(normalizedCoordToClipSpace(linePoints[i]));
  186. lineList_Pixel(points, color, meshData, 0, 0);
  187. }
  188. else
  189. {
  190. lineList_Pixel(linePoints, color, meshData, 0, 0);
  191. }
  192. HMesh mesh = Mesh::create();
  193. gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, meshData);
  194. dbgCmd.mesh = mesh;
  195. dbgCmd.worldCenter = Vector3::ZERO;
  196. if(coordType == DebugDrawCoordType::Normalized)
  197. {
  198. dbgCmd.type = DebugDrawType::ClipSpace;
  199. dbgCmd.matInfo2DClipSpace = mMaterial2DClipSpace;
  200. }
  201. else
  202. {
  203. dbgCmd.type = DebugDrawType::ScreenSpace;
  204. dbgCmd.matInfo2DScreenSpace = BuiltinMaterialManager::instance().createDebugDraw2DScreenSpaceMaterial();
  205. }
  206. }
  207. void DrawHelper2D::drawLineList_AA(const HCamera& camera, const CM::Vector<CM::Vector2>::type& linePoints, float width, float borderWidth,
  208. const CM::Color& color, DebugDrawCoordType coordType, float timeout)
  209. {
  210. const Viewport* viewport = camera->getViewport().get();
  211. Vector<DebugDrawCommand>::type& commands = mCommandsPerViewport[viewport];
  212. commands.push_back(DebugDrawCommand());
  213. DebugDrawCommand& dbgCmd = commands.back();
  214. dbgCmd.endTime = gTime().getTime() + timeout;
  215. MeshDataPtr meshData = cm_shared_ptr<MeshData, ScratchAlloc>((UINT32)(linePoints.size() * 4));
  216. meshData->beginDesc();
  217. meshData->addSubMesh((UINT32)(linePoints.size() * 15), 0, DOT_TRIANGLE_LIST);
  218. meshData->addVertElem(VET_FLOAT2, VES_POSITION);
  219. meshData->addVertElem(VET_COLOR, VES_COLOR);
  220. meshData->endDesc();
  221. if(coordType == DebugDrawCoordType::Normalized)
  222. {
  223. Vector<Vector2>::type points;
  224. UINT32 numPoints = (UINT32)linePoints.size();
  225. for(UINT32 i = 0; i < numPoints; i++)
  226. points.push_back(normalizedCoordToClipSpace(linePoints[i]));
  227. lineList_AA(points, width, borderWidth, color, meshData, 0, 0);
  228. }
  229. else
  230. {
  231. lineList_AA(linePoints, width, borderWidth, color, meshData, 0, 0);
  232. }
  233. HMesh mesh = Mesh::create();
  234. gMainSyncedCA().writeSubresource(mesh.getInternalPtr(), 0, meshData);
  235. dbgCmd.mesh = mesh;
  236. dbgCmd.worldCenter = Vector3::ZERO;
  237. if(coordType == DebugDrawCoordType::Normalized)
  238. {
  239. dbgCmd.type = DebugDrawType::ClipSpace;
  240. dbgCmd.matInfo2DClipSpace = mMaterial2DClipSpace;
  241. }
  242. else
  243. {
  244. dbgCmd.type = DebugDrawType::ScreenSpace;
  245. dbgCmd.matInfo2DScreenSpace = BuiltinMaterialManager::instance().createDebugDraw2DScreenSpaceMaterial();
  246. }
  247. }
  248. void DrawHelper2D::line_AA(const Vector2& a, const Vector2& b, float width, float borderWidth, const Color& color, UINT8* outVertices, UINT8* outColors,
  249. UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset)
  250. {
  251. Vector2 dir = b - a;
  252. dir.normalize();
  253. Vector2 nrm(dir.y, -dir.x);
  254. Vector<Vector2>::type points(4);
  255. float r = width - 1.0f;
  256. r *= 0.5f;
  257. if (r < 0.01f)
  258. r = 0.01f;
  259. dir = dir * r;
  260. nrm = nrm * r;
  261. Vector2 v0 = a - dir - nrm;
  262. Vector2 v1 = a - dir + nrm;
  263. Vector2 v2 = b + dir + nrm;
  264. Vector2 v3 = b + dir - nrm;
  265. points[0] = v0;
  266. points[1] = v1;
  267. points[2] = v2;
  268. points[3] = v3;
  269. polygon_AA(points, borderWidth, color, outVertices, outColors, vertexOffset, vertexStride, outIndices, indexOffset);
  270. }
  271. void DrawHelper2D::polygon_AA(const Vector<Vector2>::type& points, float borderWidth, const Color& color, UINT8* outVertices, UINT8* outColors,
  272. UINT32 vertexOffset, UINT32 vertexStride, UINT32* outIndices, UINT32 indexOffset)
  273. {
  274. UINT32 numCoords = (UINT32)points.size();
  275. outVertices += vertexOffset * vertexStride;
  276. Vector<Vector2>::type tempNormals(numCoords);
  277. for(UINT32 i = 0, j = numCoords - 1; i < numCoords; j = i++)
  278. {
  279. const Vector2& v0 = points[j];
  280. const Vector2& v1 = points[i];
  281. Vector2 d = v1 - v0;
  282. d.normalize();
  283. // Rotate by 90 degrees
  284. std::swap(d.x, d.y); // TODO - Not properly ported
  285. d.y = -d.y;
  286. tempNormals[j] = d;
  287. // Also start populating the vertex array
  288. Vector2* vertices = (Vector2*)outVertices;
  289. *vertices = v1;
  290. UINT32* colors = (UINT32*)outColors;
  291. *colors = color.getAsRGBA();
  292. outVertices += vertexStride;
  293. outColors += vertexStride;
  294. }
  295. Color transparentColor = color;
  296. transparentColor.a = 0.0f;
  297. for(UINT32 i = 0, j = numCoords - 1; i < numCoords; j = i++)
  298. {
  299. const Vector2& n0 = tempNormals[j];
  300. const Vector2& n1 = tempNormals[i];
  301. Vector2 avgNrm = (n0 + n1) * 0.5f;
  302. float magSqrd = avgNrm.squaredLength();
  303. if (magSqrd > 0.000001f)
  304. {
  305. float scale = 1.0f / magSqrd;
  306. if (scale > 10.0f)
  307. scale = 10.0f;
  308. avgNrm = avgNrm * scale;
  309. }
  310. Vector2 tempCoord = points[i] + avgNrm * borderWidth;
  311. // Move it to the vertex array
  312. Vector2* vertices = (Vector2*)outVertices;
  313. *vertices = tempCoord;
  314. UINT32* colors = (UINT32*)outColors;
  315. *colors = transparentColor.getAsRGBA();
  316. outVertices += vertexStride;
  317. outColors += vertexStride;
  318. }
  319. // Populate index buffer
  320. outIndices += indexOffset;
  321. UINT32 idxCnt = 0;
  322. for(UINT32 i = 0, j = numCoords - 1; i < numCoords; j = i++)
  323. {
  324. outIndices[idxCnt++] = i;
  325. outIndices[idxCnt++] = j;
  326. outIndices[idxCnt++] = numCoords + j;
  327. outIndices[idxCnt++] = numCoords + j;
  328. outIndices[idxCnt++] = numCoords + i;
  329. outIndices[idxCnt++] = i;
  330. }
  331. for(UINT32 i = 2; i < numCoords; ++i)
  332. {
  333. outIndices[idxCnt++] = 0;
  334. outIndices[idxCnt++] = i - 1;
  335. outIndices[idxCnt++] = i;
  336. }
  337. }
  338. FRect DrawHelper2D::normalizedCoordToClipSpace(const FRect& area) const
  339. {
  340. FRect clipSpaceRect;
  341. clipSpaceRect.x = area.x * 2.0f - 1.0f;
  342. clipSpaceRect.width = area.width * 2.0f;
  343. clipSpaceRect.y = -area.y * 2.0f + 1.0f;
  344. clipSpaceRect.height = area.height * -2.0f;
  345. return clipSpaceRect;
  346. }
  347. Vector2 DrawHelper2D::normalizedCoordToClipSpace(const Vector2& pos) const
  348. {
  349. return Vector2(pos.x * 2.0f - 1.0f, -pos.y * 2.0f + 1.0f);
  350. }
  351. }