ModelResource.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. // Copyright (C) 2009-2023, 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::getGeometryInfo(U32 lod, ModelPatchGeometryInfo& inf) const
  31. {
  32. lod = min<U32>(lod, m_meshLodCount - 1);
  33. inf.m_indexBufferOffset = m_lodInfos[lod].m_indexBufferOffset + m_lodInfos[lod].m_firstIndex * getIndexSize(IndexType::kU16);
  34. inf.m_indexType = IndexType::kU16;
  35. inf.m_indexCount = m_lodInfos[lod].m_indexCount;
  36. for(VertexStreamId stream : EnumIterable(VertexStreamId::kMeshRelatedFirst, VertexStreamId::kMeshRelatedCount))
  37. {
  38. inf.m_vertexBufferOffsets[stream] = m_lodInfos[lod].m_vertexBufferOffsets[stream];
  39. }
  40. }
  41. void ModelPatch::getRayTracingInfo(const RenderingKey& key, ModelRayTracingInfo& info) const
  42. {
  43. ANKI_ASSERT(!!(m_mtl->getRenderingTechniques() & RenderingTechniqueBit(1 << key.getRenderingTechnique())));
  44. // Mesh
  45. const U32 meshLod = min<U32>(key.getLod(), m_meshLodCount - 1);
  46. info.m_bottomLevelAccelerationStructure = m_mesh->getBottomLevelAccelerationStructure(meshLod);
  47. info.m_indexBufferOffset = m_lodInfos[meshLod].m_indexBufferOffset + 2_PtrSize * m_lodInfos[meshLod].m_firstIndex;
  48. // Material
  49. const MaterialVariant& variant = m_mtl->getOrCreateVariant(key);
  50. info.m_shaderGroupHandleIndex = variant.getRtShaderGroupHandleIndex();
  51. }
  52. Error ModelPatch::init([[maybe_unused]] ModelResource* model, CString meshFName, const CString& mtlFName, U32 subMeshIndex, Bool async)
  53. {
  54. #if ANKI_ASSERTIONS_ENABLED
  55. m_model = model;
  56. #endif
  57. // Load material
  58. ANKI_CHECK(ResourceManager::getSingleton().loadResource(mtlFName, m_mtl, async));
  59. // Load mesh
  60. ANKI_CHECK(ResourceManager::getSingleton().loadResource(meshFName, m_mesh, async));
  61. if(subMeshIndex != kMaxU32 && subMeshIndex >= m_mesh->getSubMeshCount())
  62. {
  63. ANKI_RESOURCE_LOGE("Wrong subMeshIndex given");
  64. return Error::kUserData;
  65. }
  66. // Init cached data
  67. if(subMeshIndex == kMaxU32)
  68. {
  69. m_aabb = m_mesh->getBoundingShape();
  70. }
  71. else
  72. {
  73. U32 firstIndex, indexCount;
  74. m_mesh->getSubMeshInfo(0, subMeshIndex, firstIndex, indexCount, m_aabb);
  75. }
  76. m_meshLodCount = m_mesh->getLodCount();
  77. for(U32 l = 0; l < m_meshLodCount; ++l)
  78. {
  79. Lod& lod = m_lodInfos[l];
  80. Aabb aabb;
  81. m_mesh->getSubMeshInfo(l, (subMeshIndex == kMaxU32) ? 0 : subMeshIndex, lod.m_firstIndex, lod.m_indexCount, aabb);
  82. U32 totalIndexCount;
  83. IndexType indexType;
  84. m_mesh->getIndexBufferInfo(l, lod.m_indexBufferOffset, totalIndexCount, indexType);
  85. for(VertexStreamId stream : EnumIterable(VertexStreamId::kMeshRelatedFirst, VertexStreamId::kMeshRelatedCount))
  86. {
  87. if(m_mesh->isVertexStreamPresent(stream))
  88. {
  89. U32 vertCount;
  90. m_mesh->getVertexStreamInfo(l, stream, lod.m_vertexBufferOffsets[stream], vertCount);
  91. }
  92. else
  93. {
  94. lod.m_vertexBufferOffsets[stream] = kMaxPtrSize;
  95. }
  96. }
  97. }
  98. return Error::kNone;
  99. }
  100. Error ModelResource::load(const ResourceFilename& filename, Bool async)
  101. {
  102. // Load
  103. //
  104. ResourceXmlDocument doc;
  105. ANKI_CHECK(openFileParseXml(filename, doc));
  106. XmlElement rootEl;
  107. ANKI_CHECK(doc.getChildElement("model", rootEl));
  108. // <modelPatches>
  109. XmlElement modelPatchesEl;
  110. ANKI_CHECK(rootEl.getChildElement("modelPatches", modelPatchesEl));
  111. XmlElement modelPatchEl;
  112. ANKI_CHECK(modelPatchesEl.getChildElement("modelPatch", modelPatchEl));
  113. // Count
  114. U32 count = 0;
  115. do
  116. {
  117. ++count;
  118. // Move to next
  119. ANKI_CHECK(modelPatchEl.getNextSiblingElement("modelPatch", modelPatchEl));
  120. } while(modelPatchEl);
  121. // Check number of model patches
  122. if(count < 1)
  123. {
  124. ANKI_RESOURCE_LOGE("Zero number of model patches");
  125. return Error::kUserData;
  126. }
  127. m_modelPatches.resize(count);
  128. count = 0;
  129. ANKI_CHECK(modelPatchesEl.getChildElement("modelPatch", modelPatchEl));
  130. do
  131. {
  132. XmlElement materialEl;
  133. ANKI_CHECK(modelPatchEl.getChildElement("material", materialEl));
  134. XmlElement meshEl;
  135. ANKI_CHECK(modelPatchEl.getChildElement("mesh", meshEl));
  136. CString meshFname;
  137. ANKI_CHECK(meshEl.getText(meshFname));
  138. U32 subMeshIndex;
  139. Bool subMeshIndexPresent;
  140. ANKI_CHECK(meshEl.getAttributeNumberOptional("subMeshIndex", subMeshIndex, subMeshIndexPresent));
  141. if(!subMeshIndexPresent)
  142. {
  143. subMeshIndex = kMaxU32;
  144. }
  145. CString cstr;
  146. ANKI_CHECK(materialEl.getText(cstr));
  147. ANKI_CHECK(m_modelPatches[count].init(this, meshFname, cstr, subMeshIndex, async));
  148. if(count > 0 && m_modelPatches[count].supportsSkinning() != m_modelPatches[count - 1].supportsSkinning())
  149. {
  150. ANKI_RESOURCE_LOGE("All model patches should support skinning or all shouldn't support skinning");
  151. return Error::kUserData;
  152. }
  153. // Move to next
  154. ANKI_CHECK(modelPatchEl.getNextSiblingElement("modelPatch", modelPatchEl));
  155. ++count;
  156. } while(modelPatchEl);
  157. ANKI_ASSERT(count == m_modelPatches.getSize());
  158. // Calculate compound bounding volume
  159. m_boundingVolume = m_modelPatches[0].m_aabb;
  160. for(auto it = m_modelPatches.getBegin() + 1; it != m_modelPatches.getEnd(); ++it)
  161. {
  162. m_boundingVolume = m_boundingVolume.getCompoundShape((*it).m_aabb);
  163. }
  164. return Error::kNone;
  165. }
  166. } // end namespace anki