2
0

DrawableProxy2D.cpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. //
  2. // Copyright (c) 2008-2014 the Urho3D project.
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #include "Precompiled.h"
  23. #include "Camera.h"
  24. #include "Context.h"
  25. #include "Drawable2D.h"
  26. #include "DrawableProxy2D.h"
  27. #include "Geometry.h"
  28. #include "IndexBuffer.h"
  29. #include "Log.h"
  30. #include "Material.h"
  31. #include "Node.h"
  32. #include "Scene.h"
  33. #include "VertexBuffer.h"
  34. #include "Sort.h"
  35. #include "DebugNew.h"
  36. namespace Urho3D
  37. {
  38. DrawableProxy2D::DrawableProxy2D(Context* context) :
  39. Drawable(context, DRAWABLE_GEOMETRY),
  40. indexBuffer_(new IndexBuffer(context_)),
  41. vertexBuffer_(new VertexBuffer(context_)),
  42. orderDirty_(true)
  43. {
  44. }
  45. DrawableProxy2D::~DrawableProxy2D()
  46. {
  47. }
  48. void DrawableProxy2D::RegisterObject(Context* context)
  49. {
  50. context->RegisterFactory<DrawableProxy2D>();
  51. }
  52. void DrawableProxy2D::UpdateBatches(const FrameInfo& frame)
  53. {
  54. unsigned count = materials_.Size();
  55. batches_.Resize(count);
  56. for (unsigned i = 0; i < count; ++i)
  57. {
  58. batches_[i].distance_ = 10.0f + (count - i) * 0.001f;
  59. batches_[i].material_ = materials_[i];
  60. batches_[i].geometry_ = geometries_[i];
  61. batches_[i].worldTransform_ = &Matrix3x4::IDENTITY;
  62. }
  63. }
  64. void DrawableProxy2D::UpdateGeometry(const FrameInfo& frame)
  65. {
  66. materials_.Clear();
  67. if (orderDirty_)
  68. {
  69. Sort(drawables_.Begin(), drawables_.End(), CompareDrawable2Ds);
  70. orderDirty_ = false;
  71. }
  72. float timeStep = frame.timeStep_;
  73. unsigned vertexCount = 0;
  74. for (unsigned i = 0; i < drawables_.Size(); ++i)
  75. vertexCount += drawables_[i]->GetVertices().Size();
  76. if (vertexCount == 0)
  77. return;
  78. unsigned indexCount = vertexCount / 4 * 6;
  79. if (indexBuffer_->GetIndexCount() < indexCount)
  80. {
  81. bool largeIndices = indexCount > 0xFFFF;
  82. indexBuffer_->SetSize(indexCount, largeIndices, true);
  83. void* buffer = indexBuffer_->Lock(0, indexCount, true);
  84. if (buffer)
  85. {
  86. unsigned quadCount = indexCount / 6;
  87. if (largeIndices)
  88. {
  89. unsigned* dest = reinterpret_cast<unsigned*>(buffer);
  90. for (unsigned i = 0; i < quadCount; ++i)
  91. {
  92. unsigned base = i * 4;
  93. dest[0] = base;
  94. dest[1] = base + 1;
  95. dest[2] = base + 2;
  96. dest[3] = base;
  97. dest[4] = base + 2;
  98. dest[5] = base + 3;
  99. dest += 6;
  100. }
  101. }
  102. else
  103. {
  104. unsigned short* dest = reinterpret_cast<unsigned short*>(buffer);
  105. for (unsigned i = 0; i < quadCount; ++i)
  106. {
  107. unsigned base = i * 4;
  108. dest[0] = (unsigned short)(base);
  109. dest[1] = (unsigned short)(base + 1);
  110. dest[2] = (unsigned short)(base + 2);
  111. dest[3] = (unsigned short)(base);
  112. dest[4] = (unsigned short)(base + 2);
  113. dest[5] = (unsigned short)(base + 3);
  114. dest += 6;
  115. }
  116. }
  117. indexBuffer_->Unlock();
  118. }
  119. else
  120. {
  121. LOGERROR("Failed to lock index buffer");
  122. return;
  123. }
  124. }
  125. if (vertexBuffer_->GetVertexCount() < vertexCount)
  126. vertexBuffer_->SetSize(vertexCount, MASK_VERTEX2D);
  127. Vertex2D* dest = reinterpret_cast<Vertex2D*>(vertexBuffer_->Lock(0, vertexCount, true));
  128. if (dest)
  129. {
  130. Material* material = 0;
  131. unsigned iStart = 0;
  132. unsigned iCount = 0;
  133. unsigned vStart = 0;
  134. unsigned vCount = 0;
  135. for (unsigned d = 0; d < drawables_.Size(); ++d)
  136. {
  137. Material* usedMaterial = drawables_[d]->GetUsedMaterial();
  138. const Vector<Vertex2D>& vertices = drawables_[d]->GetVertices();
  139. if (!usedMaterial || vertices.Empty())
  140. continue;
  141. if (material != usedMaterial)
  142. {
  143. if (material)
  144. {
  145. AddBatch(material, iStart, iCount, vStart, vCount);
  146. iStart += iCount;
  147. iCount = 0;
  148. vStart += vCount;
  149. vCount = 0;
  150. }
  151. material = usedMaterial;
  152. }
  153. for (unsigned i = 0; i < vertices.Size(); ++i)
  154. dest[i] = vertices[i];
  155. dest += vertices.Size();
  156. iCount += vertices.Size() / 4 * 6;
  157. vCount += vertices.Size();
  158. }
  159. if (material)
  160. AddBatch(material, iStart, iCount, vStart, vCount);
  161. vertexBuffer_->Unlock();
  162. }
  163. else
  164. LOGERROR("Failed to lock vertex buffer");
  165. }
  166. UpdateGeometryType DrawableProxy2D::GetUpdateGeometryType()
  167. {
  168. return UPDATE_MAIN_THREAD;
  169. }
  170. void DrawableProxy2D::AddDrawable(Drawable2D* drawable)
  171. {
  172. if (!drawable)
  173. return;
  174. if (drawables_.Contains(drawable))
  175. return;
  176. drawables_.Push(drawable);
  177. orderDirty_ = true;
  178. }
  179. void DrawableProxy2D::RemoveDrawable(Drawable2D* drawable)
  180. {
  181. if (!drawable)
  182. return;
  183. drawables_.Remove(drawable);
  184. orderDirty_ = true;
  185. }
  186. void DrawableProxy2D::OnNodeSet(Node* node)
  187. {
  188. Drawable::OnNodeSet(node);
  189. Scene* scene = GetScene();
  190. if (scene)
  191. {
  192. PODVector<Camera*> cameras;
  193. scene->GetComponents(cameras, true);
  194. if (!cameras.Empty())
  195. cameraNode_ = cameras[0]->GetNode();
  196. }
  197. }
  198. void DrawableProxy2D::OnWorldBoundingBoxUpdate()
  199. {
  200. boundingBox_.Clear();
  201. if (cameraNode_)
  202. {
  203. // Create dummy bounding box
  204. Vector3 position = cameraNode_->GetWorldPosition();
  205. boundingBox_.Merge(Vector3(position.x_, position.y_, 20.0f));
  206. }
  207. worldBoundingBox_ = boundingBox_;
  208. }
  209. void DrawableProxy2D::AddBatch(Material* material, unsigned indexStart, unsigned indexCount, unsigned vertexStart, unsigned vertexCount)
  210. {
  211. if (!material || indexCount == 0 || vertexCount == 0)
  212. return;
  213. materials_.Push(SharedPtr<Material>(material));
  214. unsigned batchSize = materials_.Size();
  215. if (geometries_.Size() < batchSize)
  216. {
  217. SharedPtr<Geometry> geometry(new Geometry(context_));
  218. geometry->SetIndexBuffer(indexBuffer_);
  219. geometry->SetVertexBuffer(0, vertexBuffer_, MASK_VERTEX2D);
  220. geometries_.Push(geometry);
  221. }
  222. geometries_[batchSize - 1]->SetDrawRange(TRIANGLE_LIST, indexStart, indexCount, vertexStart, vertexCount);
  223. }
  224. }