CDynamicMeshBuffer.h 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. // Copyright (C) 2008-2012 Nikolaus Gebhardt
  2. // This file is part of the "Irrlicht Engine".
  3. // For conditions of distribution and use, see copyright notice in irrlicht.h
  4. #ifndef IRR_C_DYNAMIC_MESHBUFFER_H_INCLUDED
  5. #define IRR_C_DYNAMIC_MESHBUFFER_H_INCLUDED
  6. #include "IDynamicMeshBuffer.h"
  7. #include "CVertexBuffer.h"
  8. #include "CIndexBuffer.h"
  9. namespace irr
  10. {
  11. namespace scene
  12. {
  13. //! Implementation of the IMeshBuffer interface for which can work with 16 and 32 bit indices as well as different vertex types
  14. class CDynamicMeshBuffer: public IDynamicMeshBuffer
  15. {
  16. public:
  17. //! constructor
  18. CDynamicMeshBuffer(video::E_VERTEX_TYPE vertexType, video::E_INDEX_TYPE indexType)
  19. : PrimitiveType(EPT_TRIANGLES)
  20. {
  21. VertexBuffer=new CVertexBuffer(vertexType);
  22. IndexBuffer=new CIndexBuffer(indexType);
  23. }
  24. //! destructor
  25. virtual ~CDynamicMeshBuffer()
  26. {
  27. if (VertexBuffer)
  28. VertexBuffer->drop();
  29. if (IndexBuffer)
  30. IndexBuffer->drop();
  31. }
  32. virtual IVertexBuffer& getVertexBuffer() const IRR_OVERRIDE
  33. {
  34. return *VertexBuffer;
  35. }
  36. virtual IIndexBuffer& getIndexBuffer() const IRR_OVERRIDE
  37. {
  38. return *IndexBuffer;
  39. }
  40. virtual void setVertexBuffer(IVertexBuffer *newVertexBuffer) IRR_OVERRIDE
  41. {
  42. if (newVertexBuffer)
  43. newVertexBuffer->grab();
  44. if (VertexBuffer)
  45. VertexBuffer->drop();
  46. VertexBuffer=newVertexBuffer;
  47. }
  48. virtual void setIndexBuffer(IIndexBuffer *newIndexBuffer) IRR_OVERRIDE
  49. {
  50. if (newIndexBuffer)
  51. newIndexBuffer->grab();
  52. if (IndexBuffer)
  53. IndexBuffer->drop();
  54. IndexBuffer=newIndexBuffer;
  55. }
  56. //! Get Material of this buffer.
  57. virtual const video::SMaterial& getMaterial() const IRR_OVERRIDE
  58. {
  59. return Material;
  60. }
  61. //! Get Material of this buffer.
  62. virtual video::SMaterial& getMaterial() IRR_OVERRIDE
  63. {
  64. return Material;
  65. }
  66. //! Get bounding box
  67. virtual const core::aabbox3d<f32>& getBoundingBox() const IRR_OVERRIDE
  68. {
  69. return BoundingBox;
  70. }
  71. //! Set bounding box
  72. virtual void setBoundingBox( const core::aabbox3df& box) IRR_OVERRIDE
  73. {
  74. BoundingBox = box;
  75. }
  76. //! Recalculate bounding box
  77. virtual void recalculateBoundingBox() IRR_OVERRIDE
  78. {
  79. if (!getVertexBuffer().size())
  80. BoundingBox.reset(0,0,0);
  81. else
  82. {
  83. BoundingBox.reset(getVertexBuffer()[0].Pos);
  84. for (u32 i=1; i<getVertexBuffer().size(); ++i)
  85. BoundingBox.addInternalPoint(getVertexBuffer()[i].Pos);
  86. }
  87. }
  88. //! Append the vertices and indices to the current buffer
  89. /** Only works for compatible vertex types.
  90. \param vertices Pointer to a vertex array.
  91. \param numVertices Number of vertices in the array.
  92. \param indices Pointer to index array.
  93. \param numIndices Number of indices in array. */
  94. virtual void append(const void* const vertices, u32 numVertices, const u16* const indices, u32 numIndices, bool updateBoundingBox=true) IRR_OVERRIDE
  95. {
  96. // We simply assume it has the same vertex and index type as this object. If other types are passed this will crash
  97. append(getVertexType(), vertices, numVertices, getIndexType(), indices, numIndices, updateBoundingBox);
  98. }
  99. //! Append the meshbuffer to the current buffer
  100. /** \param other Buffer to append to this one. */
  101. virtual void append(const IMeshBuffer* const other, bool updateBoundingBox=true) IRR_OVERRIDE
  102. {
  103. append(other->getVertexType(), other->getVertices(), other->getVertexCount(), other->getIndexType(), other->getIndices(), other->getIndexCount(), updateBoundingBox);
  104. }
  105. void append(video::E_VERTEX_TYPE vertexType, const void* const vertices, u32 numVertices, video::E_INDEX_TYPE indexType, const void* const indices, u32 numIndices, bool updateBoundingBox)
  106. {
  107. if (vertices == getVertices() || indices == getIndices()) // can't do that because we're doing reallocations on those blocks
  108. return;
  109. const u32 vertexCount = getVertexCount();
  110. VertexBuffer->reallocate(vertexCount+numVertices, false);
  111. if ( vertexType == getVertexType() )
  112. {
  113. const irr::u32 typeSize = getVertexPitchFromType(vertexType);
  114. VertexBuffer->set_used(vertexCount+numVertices);
  115. irr::u8* target = &static_cast<irr::u8*>(VertexBuffer->pointer())[vertexCount*typeSize];
  116. memcpy(target, vertices, numVertices*typeSize);
  117. }
  118. else
  119. {
  120. switch ( vertexType )
  121. {
  122. case video::EVT_STANDARD:
  123. for (u32 i=0; i<numVertices; ++i)
  124. {
  125. VertexBuffer->push_back(static_cast<const video::S3DVertex*>(vertices)[i]);
  126. }
  127. break;
  128. case video::EVT_2TCOORDS:
  129. for (u32 i=0; i<numVertices; ++i)
  130. {
  131. VertexBuffer->push_back(static_cast<const video::S3DVertex2TCoords*>(vertices)[i]);
  132. }
  133. break;
  134. case video::EVT_TANGENTS:
  135. for (u32 i=0; i<numVertices; ++i)
  136. {
  137. VertexBuffer->push_back(static_cast<const video::S3DVertexTangents*>(vertices)[i]);
  138. }
  139. break;
  140. }
  141. }
  142. if ( updateBoundingBox && numVertices > 0)
  143. {
  144. if ( vertexCount == 0 )
  145. BoundingBox.reset( static_cast<const video::S3DVertex*>(vertices)[0].Pos );
  146. const u32 typePitch = getVertexPitchFromType(vertexType);
  147. const irr::u8* v8 = static_cast<const irr::u8*>(vertices);
  148. for (u32 i=0; i<numVertices; ++i, v8 += typePitch)
  149. {
  150. BoundingBox.addInternalPoint(reinterpret_cast<const video::S3DVertex*>(v8)->Pos);
  151. }
  152. }
  153. IndexBuffer->reallocate(getIndexCount()+numIndices, false);
  154. switch ( indexType )
  155. {
  156. case video::EIT_16BIT:
  157. {
  158. const irr::u16* indices16 = reinterpret_cast<const irr::u16*>(indices);
  159. for (u32 i=0; i<numIndices; ++i)
  160. {
  161. // Note: This can overflow, not checked. Will result in broken models, but no crashes.
  162. IndexBuffer->push_back(indices16[i]+vertexCount);
  163. }
  164. break;
  165. }
  166. case video::EIT_32BIT:
  167. {
  168. const irr::u32* indices32 = reinterpret_cast<const irr::u32*>(indices);
  169. for (u32 i=0; i<numIndices; ++i)
  170. {
  171. IndexBuffer->push_back(indices32[i]+vertexCount);
  172. }
  173. break;
  174. }
  175. }
  176. setDirty();
  177. }
  178. //! Describe what kind of primitive geometry is used by the meshbuffer
  179. virtual void setPrimitiveType(E_PRIMITIVE_TYPE type) IRR_OVERRIDE
  180. {
  181. PrimitiveType = type;
  182. }
  183. //! Get the kind of primitive geometry which is used by the meshbuffer
  184. virtual E_PRIMITIVE_TYPE getPrimitiveType() const IRR_OVERRIDE
  185. {
  186. return PrimitiveType;
  187. }
  188. //! Returns type of the class implementing the IMeshBuffer
  189. virtual EMESH_BUFFER_TYPE getType() const IRR_OVERRIDE
  190. {
  191. return EMBT_DYNAMIC;
  192. }
  193. //! Create copy of the meshbuffer
  194. virtual IMeshBuffer* createClone(int cloneFlags) const IRR_OVERRIDE
  195. {
  196. CDynamicMeshBuffer* clone = new CDynamicMeshBuffer(VertexBuffer->getType(), IndexBuffer->getType());
  197. if (cloneFlags & ECF_VERTICES)
  198. {
  199. const u32 numVertices = VertexBuffer->size();
  200. clone->VertexBuffer->reallocate(numVertices);
  201. for ( u32 i=0; i<numVertices; ++i )
  202. {
  203. clone->VertexBuffer->push_back((*VertexBuffer)[i]);
  204. }
  205. clone->BoundingBox = BoundingBox;
  206. }
  207. if (cloneFlags & ECF_INDICES)
  208. {
  209. const u32 numIndices = IndexBuffer->size();
  210. clone->IndexBuffer->reallocate(numIndices);
  211. for ( u32 i=0; i<numIndices; ++i )
  212. {
  213. clone->IndexBuffer->push_back((*IndexBuffer)[i]);
  214. }
  215. }
  216. clone->VertexBuffer->setHardwareMappingHint(VertexBuffer->getHardwareMappingHint());
  217. clone->IndexBuffer->setHardwareMappingHint(clone->IndexBuffer->getHardwareMappingHint());
  218. clone->Material = Material;
  219. clone->PrimitiveType = PrimitiveType;
  220. return clone;
  221. }
  222. video::SMaterial Material;
  223. core::aabbox3d<f32> BoundingBox;
  224. //! Primitive type used for rendering (triangles, lines, ...)
  225. E_PRIMITIVE_TYPE PrimitiveType;
  226. private:
  227. CDynamicMeshBuffer(const CDynamicMeshBuffer&); // = delete in c++11, prevent copying
  228. IVertexBuffer *VertexBuffer;
  229. IIndexBuffer *IndexBuffer;
  230. };
  231. } // end namespace scene
  232. } // end namespace irr
  233. #endif