ModelResource.cpp 6.4 KB

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