ModelResource.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. // Copyright (C) 2009-2022, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/Resource/ModelResource.h>
  6. #include <AnKi/Resource/ResourceManager.h>
  7. #include <AnKi/Resource/MeshResource.h>
  8. #include <AnKi/Util/Xml.h>
  9. #include <AnKi/Util/Logger.h>
  10. namespace anki {
  11. void ModelPatch::getRenderingInfo(const RenderingKey& key, ModelRenderingInfo& inf) const
  12. {
  13. ANKI_ASSERT(!(!supportsSkinning() && key.getSkinned()));
  14. const U32 meshLod = min<U32>(key.getLod(), m_meshLodCount - 1);
  15. // Vertex attributes & bindings
  16. {
  17. inf.m_indexBufferOffset = m_lodInfos[meshLod].m_indexBufferOffset;
  18. inf.m_indexType = IndexType::kU16;
  19. inf.m_firstIndex = m_lodInfos[meshLod].m_firstIndex;
  20. inf.m_indexCount = m_lodInfos[meshLod].m_indexCount;
  21. for(VertexStreamId stream : EnumIterable(VertexStreamId::kMeshRelatedFirst, VertexStreamId::kMeshRelatedCount))
  22. {
  23. inf.m_vertexBufferOffsets[stream] = m_lodInfos[meshLod].m_vertexBufferOffsets[stream];
  24. }
  25. }
  26. // Get program
  27. const MaterialVariant& variant = m_mtl->getOrCreateVariant(key);
  28. inf.m_program = variant.getShaderProgram();
  29. }
  30. void ModelPatch::getRayTracingInfo(const RenderingKey& key, ModelRayTracingInfo& info) const
  31. {
  32. ANKI_ASSERT(!!(m_mtl->getRenderingTechniques() & RenderingTechniqueBit(1 << key.getRenderingTechnique())));
  33. // Mesh
  34. const U32 meshLod = min<U32>(key.getLod(), m_meshLodCount - 1);
  35. info.m_bottomLevelAccelerationStructure = m_mesh->getBottomLevelAccelerationStructure(meshLod);
  36. // Material
  37. const MaterialVariant& variant = m_mtl->getOrCreateVariant(key);
  38. info.m_shaderGroupHandleIndex = variant.getRtShaderGroupHandleIndex();
  39. }
  40. Error ModelPatch::init([[maybe_unused]] ModelResource* model, CString meshFName, const CString& mtlFName,
  41. U32 subMeshIndex, Bool async, ResourceManager* manager)
  42. {
  43. #if ANKI_ENABLE_ASSERTIONS
  44. m_model = model;
  45. #endif
  46. // Load material
  47. ANKI_CHECK(manager->loadResource(mtlFName, m_mtl, async));
  48. // Load mesh
  49. ANKI_CHECK(manager->loadResource(meshFName, m_mesh, async));
  50. if(subMeshIndex != kMaxU32 && subMeshIndex >= m_mesh->getSubMeshCount())
  51. {
  52. ANKI_RESOURCE_LOGE("Wrong subMeshIndex given");
  53. return Error::kUserData;
  54. }
  55. // Init cached data
  56. if(subMeshIndex == kMaxU32)
  57. {
  58. m_aabb = m_mesh->getBoundingShape();
  59. }
  60. else
  61. {
  62. U32 firstIndex, indexCount;
  63. m_mesh->getSubMeshInfo(0, subMeshIndex, firstIndex, indexCount, m_aabb);
  64. }
  65. m_meshLodCount = m_mesh->getLodCount();
  66. for(U32 l = 0; l < m_meshLodCount; ++l)
  67. {
  68. Lod& lod = m_lodInfos[l];
  69. Aabb aabb;
  70. m_mesh->getSubMeshInfo(l, (subMeshIndex == kMaxU32) ? 0 : subMeshIndex, lod.m_firstIndex, lod.m_indexCount,
  71. aabb);
  72. U32 totalIndexCount;
  73. IndexType indexType;
  74. m_mesh->getIndexBufferInfo(l, lod.m_indexBufferOffset, totalIndexCount, indexType);
  75. for(VertexStreamId stream : EnumIterable(VertexStreamId::kMeshRelatedFirst, VertexStreamId::kMeshRelatedCount))
  76. {
  77. if(m_mesh->isVertexStreamPresent(stream))
  78. {
  79. U32 vertCount;
  80. m_mesh->getVertexStreamInfo(l, stream, lod.m_vertexBufferOffsets[stream], vertCount);
  81. }
  82. else
  83. {
  84. lod.m_vertexBufferOffsets[stream] = kMaxPtrSize;
  85. }
  86. }
  87. }
  88. return Error::kNone;
  89. }
  90. ModelResource::ModelResource(ResourceManager* manager)
  91. : ResourceObject(manager)
  92. {
  93. }
  94. ModelResource::~ModelResource()
  95. {
  96. m_modelPatches.destroy(getMemoryPool());
  97. }
  98. Error ModelResource::load(const ResourceFilename& filename, Bool async)
  99. {
  100. // Load
  101. //
  102. XmlElement el;
  103. XmlDocument doc(&getTempMemoryPool());
  104. ANKI_CHECK(openFileParseXml(filename, doc));
  105. XmlElement rootEl;
  106. ANKI_CHECK(doc.getChildElement("model", rootEl));
  107. // <modelPatches>
  108. XmlElement modelPatchesEl;
  109. ANKI_CHECK(rootEl.getChildElement("modelPatches", modelPatchesEl));
  110. XmlElement modelPatchEl;
  111. ANKI_CHECK(modelPatchesEl.getChildElement("modelPatch", modelPatchEl));
  112. // Count
  113. U32 count = 0;
  114. do
  115. {
  116. ++count;
  117. // Move to next
  118. ANKI_CHECK(modelPatchEl.getNextSiblingElement("modelPatch", modelPatchEl));
  119. } while(modelPatchEl);
  120. // Check number of model patches
  121. if(count < 1)
  122. {
  123. ANKI_RESOURCE_LOGE("Zero number of model patches");
  124. return Error::kUserData;
  125. }
  126. m_modelPatches.create(getMemoryPool(), count);
  127. count = 0;
  128. ANKI_CHECK(modelPatchesEl.getChildElement("modelPatch", modelPatchEl));
  129. do
  130. {
  131. XmlElement materialEl;
  132. ANKI_CHECK(modelPatchEl.getChildElement("material", materialEl));
  133. XmlElement meshEl;
  134. ANKI_CHECK(modelPatchEl.getChildElement("mesh", meshEl));
  135. CString meshFname;
  136. ANKI_CHECK(meshEl.getText(meshFname));
  137. U32 subMeshIndex;
  138. Bool subMeshIndexPresent;
  139. ANKI_CHECK(meshEl.getAttributeNumberOptional("subMeshIndex", subMeshIndex, subMeshIndexPresent));
  140. if(!subMeshIndexPresent)
  141. {
  142. subMeshIndex = kMaxU32;
  143. }
  144. CString cstr;
  145. ANKI_CHECK(materialEl.getText(cstr));
  146. ANKI_CHECK(m_modelPatches[count].init(this, meshFname, cstr, subMeshIndex, async, &getManager()));
  147. if(count > 0 && m_modelPatches[count].supportsSkinning() != m_modelPatches[count - 1].supportsSkinning())
  148. {
  149. ANKI_RESOURCE_LOGE("All model patches should support skinning or all shouldn't support skinning");
  150. return Error::kUserData;
  151. }
  152. // Move to next
  153. ANKI_CHECK(modelPatchEl.getNextSiblingElement("modelPatch", modelPatchEl));
  154. ++count;
  155. } while(modelPatchEl);
  156. ANKI_ASSERT(count == m_modelPatches.getSize());
  157. // Calculate compound bounding volume
  158. m_boundingVolume = m_modelPatches[0].m_aabb;
  159. for(auto it = m_modelPatches.getBegin() + 1; it != m_modelPatches.getEnd(); ++it)
  160. {
  161. m_boundingVolume = m_boundingVolume.getCompoundShape((*it).m_aabb);
  162. }
  163. return Error::kNone;
  164. }
  165. } // end namespace anki