ModelResource.cpp 6.1 KB

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