CmMesh.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. #include "CmMesh.h"
  2. #include "CmMeshRTTI.h"
  3. #include "CmMeshData.h"
  4. #include "CmVector2.h"
  5. #include "CmVector3.h"
  6. #include "CmDebug.h"
  7. #include "CmHardwareBufferManager.h"
  8. #include "CmMeshManager.h"
  9. #include "CmRenderSystem.h"
  10. #include "CmAsyncOp.h"
  11. #if CM_DEBUG_MODE
  12. #define THROW_IF_NOT_RENDER_THREAD throwIfNotRenderThread();
  13. #else
  14. #define THROW_IF_NOT_RENDER_THREAD
  15. #endif
  16. namespace CamelotFramework
  17. {
  18. Mesh::Mesh()
  19. :mVertexData(nullptr), mIndexData(nullptr)
  20. {
  21. }
  22. Mesh::~Mesh()
  23. {
  24. }
  25. void Mesh::setMeshData(MeshDataPtr meshData)
  26. {
  27. RenderSystem::instancePtr()->queueCommand(boost::bind(&Mesh::setMeshData_internal, this, meshData), true);
  28. }
  29. void Mesh::setMeshData_internal(MeshDataPtr meshData)
  30. {
  31. THROW_IF_NOT_RENDER_THREAD;
  32. if(meshData == nullptr)
  33. {
  34. CM_EXCEPT(InvalidParametersException, "Cannot load mesh. Mesh data is null.");
  35. }
  36. mSubMeshes.clear();
  37. if(mVertexData != nullptr)
  38. CM_DELETE(mVertexData, VertexData, PoolAlloc);
  39. if(mIndexData != nullptr)
  40. CM_DELETE(mIndexData, IndexData, PoolAlloc);
  41. // Submeshes
  42. for(UINT32 i = 0; i < meshData->getNumSubmeshes(); i++)
  43. {
  44. UINT32 numIndices = meshData->getNumIndices(i);
  45. if(numIndices > 0)
  46. {
  47. mSubMeshes.push_back(SubMesh(meshData->getIndexBufferOffset(i), numIndices));
  48. }
  49. }
  50. // Indices
  51. mIndexData = CM_NEW(IndexData, PoolAlloc) IndexData();
  52. mIndexData->indexCount = meshData->getNumIndices();
  53. mIndexData->indexBuffer = HardwareBufferManager::instance().createIndexBuffer(
  54. meshData->getIndexType(),
  55. mIndexData->indexCount,
  56. GBU_STATIC);
  57. UINT8* idxData = static_cast<UINT8*>(mIndexData->indexBuffer->lock(GBL_WRITE_ONLY_DISCARD));
  58. UINT32 idxElementSize = meshData->getIndexElementSize();
  59. UINT32 indicesSize = meshData->getIndexBufferSize();
  60. UINT8* srcIdxData = meshData->getIndexData();
  61. memcpy(idxData, srcIdxData, indicesSize);
  62. mIndexData->indexBuffer->unlock();
  63. // Vertices
  64. mVertexData = CM_NEW(VertexData, PoolAlloc) VertexData();
  65. mVertexData->vertexCount = meshData->getNumVertices();
  66. mVertexData->vertexDeclaration = meshData->createDeclaration();
  67. for(UINT32 i = 0; i <= meshData->getMaxStreamIdx(); i++)
  68. {
  69. if(!meshData->hasStream(i))
  70. continue;
  71. UINT32 streamSize = meshData->getStreamSize(i);
  72. VertexBufferPtr vertexBuffer = HardwareBufferManager::instance().createVertexBuffer(
  73. mVertexData->vertexDeclaration->getVertexSize(i),
  74. mVertexData->vertexCount,
  75. GBU_STATIC);
  76. mVertexData->setBuffer(i, vertexBuffer);
  77. UINT8* srcVertBufferData = meshData->getStreamData(i);
  78. UINT8* vertBufferData = static_cast<UINT8*>(vertexBuffer->lock(GBL_WRITE_ONLY_DISCARD));
  79. UINT32 bufferSize = meshData->getStreamSize(i);
  80. memcpy(vertBufferData, srcVertBufferData, bufferSize);
  81. vertexBuffer->unlock();
  82. }
  83. }
  84. MeshDataPtr Mesh::getMeshData()
  85. {
  86. AsyncOp op = RenderSystem::instancePtr()->queueReturnCommand(boost::bind(&Mesh::getMeshData_internal, this, _1), true);
  87. return op.getReturnValue<MeshDataPtr>();
  88. }
  89. void Mesh::getMeshData_internal(AsyncOp& asyncOp)
  90. {
  91. IndexBuffer::IndexType indexType = IndexBuffer::IT_32BIT;
  92. if(mIndexData)
  93. indexType = mIndexData->indexBuffer->getType();
  94. MeshDataPtr meshData(CM_NEW(MeshData, PoolAlloc) MeshData(mVertexData->vertexCount, indexType),
  95. &MemAllocDeleter<MeshData, PoolAlloc>::deleter);
  96. meshData->beginDesc();
  97. if(mIndexData)
  98. {
  99. UINT8* idxData = static_cast<UINT8*>(mIndexData->indexBuffer->lock(GBL_READ_ONLY));
  100. UINT32 idxElemSize = mIndexData->indexBuffer->getIndexSize();
  101. for(UINT32 i = 0; i < mSubMeshes.size(); i++)
  102. meshData->addSubMesh(mSubMeshes[i].indexCount, i);
  103. mIndexData->indexBuffer->unlock();
  104. }
  105. if(mVertexData)
  106. {
  107. auto vertexBuffers = mVertexData->getBuffers();
  108. UINT32 streamIdx = 0;
  109. for(auto iter = vertexBuffers.begin(); iter != vertexBuffers.end() ; ++iter)
  110. {
  111. VertexBufferPtr vertexBuffer = iter->second;
  112. UINT32 vertexSize = vertexBuffer->getVertexSize();
  113. UINT32 numElements = mVertexData->vertexDeclaration->getElementCount();
  114. for(UINT32 j = 0; j < numElements; j++)
  115. {
  116. const VertexElement* element = mVertexData->vertexDeclaration->getElement(j);
  117. VertexElementType type = element->getType();
  118. VertexElementSemantic semantic = element->getSemantic();
  119. UINT32 semanticIdx = element->getSemanticIdx();
  120. UINT32 offset = element->getOffset();
  121. UINT32 elemSize = element->getSize();
  122. meshData->addVertElem(type, semantic, semanticIdx, streamIdx);
  123. }
  124. streamIdx++;
  125. }
  126. }
  127. meshData->endDesc();
  128. if(mIndexData)
  129. {
  130. UINT8* idxData = static_cast<UINT8*>(mIndexData->indexBuffer->lock(GBL_READ_ONLY));
  131. UINT32 idxElemSize = mIndexData->indexBuffer->getIndexSize();
  132. for(UINT32 i = 0; i < mSubMeshes.size(); i++)
  133. {
  134. UINT8* indices = nullptr;
  135. if(indexType == IndexBuffer::IT_16BIT)
  136. indices = (UINT8*)meshData->getIndices16(i);
  137. else
  138. indices = (UINT8*)meshData->getIndices32(i);
  139. memcpy(indices, &idxData[mSubMeshes[i].indexOffset * idxElemSize], mSubMeshes[i].indexCount * idxElemSize);
  140. }
  141. mIndexData->indexBuffer->unlock();
  142. }
  143. if(mVertexData)
  144. {
  145. auto vertexBuffers = mVertexData->getBuffers();
  146. UINT32 streamIdx = 0;
  147. for(auto iter = vertexBuffers.begin(); iter != vertexBuffers.end() ; ++iter)
  148. {
  149. VertexBufferPtr vertexBuffer = iter->second;
  150. UINT32 bufferSize = vertexBuffer->getVertexSize() * vertexBuffer->getNumVertices();
  151. UINT8* vertDataPtr = static_cast<UINT8*>(vertexBuffer->lock(GBL_READ_ONLY));
  152. UINT8* dest = meshData->getStreamData(streamIdx);
  153. memcpy(dest, vertDataPtr, bufferSize);
  154. vertexBuffer->unlock();
  155. streamIdx++;
  156. }
  157. }
  158. asyncOp.completeOperation(meshData);
  159. }
  160. RenderOperation Mesh::getRenderOperation(UINT32 subMeshIdx) const
  161. {
  162. if(subMeshIdx < 0 || subMeshIdx >= mSubMeshes.size())
  163. {
  164. CM_EXCEPT(InvalidParametersException, "Invalid sub-mesh index ("
  165. + toString(subMeshIdx) + "). Number of sub-meshes available: " + toString(mSubMeshes.size()));
  166. }
  167. // TODO - BIG TODO - Completely ignores subMeshIdx and always renders the entire thing
  168. RenderOperation ro;
  169. ro.indexData = mIndexData;
  170. ro.vertexData = mVertexData;
  171. ro.useIndexes = true;
  172. ro.operationType = DOT_TRIANGLE_LIST;
  173. return ro;
  174. }
  175. void Mesh::initialize_internal()
  176. {
  177. THROW_IF_NOT_RENDER_THREAD;
  178. // TODO Low priority - Initialize an empty mesh. A better way would be to only initialize the mesh
  179. // once we set the proper mesh data (then we don't have to do it twice), but this makes the code less complex.
  180. // Consider changing it if there are performance issues.
  181. setMeshData_internal(MeshManager::instance().getNullMeshData());
  182. Resource::initialize_internal();
  183. }
  184. void Mesh::destroy_internal()
  185. {
  186. THROW_IF_NOT_RENDER_THREAD;
  187. if(mVertexData != nullptr)
  188. CM_DELETE(mVertexData, VertexData, PoolAlloc);
  189. if(mIndexData != nullptr)
  190. CM_DELETE(mIndexData, IndexData, PoolAlloc);
  191. Resource::destroy_internal();
  192. }
  193. void Mesh::throwIfNotRenderThread() const
  194. {
  195. if(CM_THREAD_CURRENT_ID != RenderSystem::instancePtr()->getRenderThreadId())
  196. CM_EXCEPT(InternalErrorException, "Calling an internal texture method from a non-render thread!");
  197. }
  198. /************************************************************************/
  199. /* SERIALIZATION */
  200. /************************************************************************/
  201. RTTITypeBase* Mesh::getRTTIStatic()
  202. {
  203. return MeshRTTI::instance();
  204. }
  205. RTTITypeBase* Mesh::getRTTI() const
  206. {
  207. return Mesh::getRTTIStatic();
  208. }
  209. /************************************************************************/
  210. /* STATICS */
  211. /************************************************************************/
  212. HMesh Mesh::create()
  213. {
  214. MeshPtr meshPtr = MeshManager::instance().create();
  215. return static_resource_cast<Mesh>(Resource::_createResourceHandle(meshPtr));
  216. }
  217. }
  218. #undef THROW_IF_NOT_RENDER_THREAD