ModelResource.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. // Copyright (C) 2009-2020, 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/resource/MeshLoader.h>
  9. #include <anki/util/Xml.h>
  10. #include <anki/util/Logger.h>
  11. namespace anki
  12. {
  13. static Bool attributeIsRequired(VertexAttributeLocation loc, Pass pass, Bool hasSkin)
  14. {
  15. if(pass == Pass::GB || pass == Pass::FS)
  16. {
  17. return true;
  18. }
  19. else if(!hasSkin)
  20. {
  21. return loc == VertexAttributeLocation::POSITION;
  22. }
  23. else
  24. {
  25. return loc == VertexAttributeLocation::POSITION || loc == VertexAttributeLocation::BONE_INDICES
  26. || loc == VertexAttributeLocation::BONE_WEIGHTS;
  27. }
  28. }
  29. void ModelPatch::getRenderingInfo(const RenderingKey& key, WeakArray<U8> subMeshIndicesArray,
  30. ModelRenderingInfo& inf) const
  31. {
  32. const Bool hasSkin = m_model->getSkeleton().isCreated();
  33. // Get the resources
  34. RenderingKey meshKey = key;
  35. meshKey.setLod(min<U32>(key.getLod(), m_meshCount - 1));
  36. const MeshResource& mesh = getMesh(meshKey);
  37. // Get program
  38. {
  39. RenderingKey mtlKey = key;
  40. mtlKey.setLod(min(key.getLod(), m_mtl->getLodCount() - 1));
  41. mtlKey.setSkinned(hasSkin);
  42. const MaterialVariant& variant = m_mtl->getOrCreateVariant(mtlKey);
  43. inf.m_program = variant.getShaderProgram();
  44. inf.m_boneTransformsBinding = m_mtl->getBoneTransformsBinding();
  45. inf.m_prevFrameBoneTransformsBinding = m_mtl->getPrevFrameBoneTransformsBinding();
  46. }
  47. // Vertex attributes & bindings
  48. {
  49. U32 bufferBindingVisitedMask = 0;
  50. Array<U32, MAX_VERTEX_ATTRIBUTES> realBufferBindingToVirtual;
  51. inf.m_vertexAttributeCount = 0;
  52. inf.m_vertexBufferBindingCount = 0;
  53. for(VertexAttributeLocation loc = VertexAttributeLocation::FIRST; loc < VertexAttributeLocation::COUNT; ++loc)
  54. {
  55. if(!mesh.isVertexAttributePresent(loc) || !attributeIsRequired(loc, key.getPass(), hasSkin))
  56. {
  57. continue;
  58. }
  59. // Attribute
  60. VertexAttributeInfo& attrib = inf.m_vertexAttributes[inf.m_vertexAttributeCount++];
  61. attrib.m_location = loc;
  62. mesh.getVertexAttributeInfo(loc, attrib.m_bufferBinding, attrib.m_format, attrib.m_relativeOffset);
  63. // Binding. Also, remove any holes in the bindings
  64. if(!(bufferBindingVisitedMask & (1 << attrib.m_bufferBinding)))
  65. {
  66. bufferBindingVisitedMask |= 1 << attrib.m_bufferBinding;
  67. VertexBufferBinding& binding = inf.m_vertexBufferBindings[inf.m_vertexBufferBindingCount];
  68. mesh.getVertexBufferInfo(attrib.m_bufferBinding, binding.m_buffer, binding.m_offset, binding.m_stride);
  69. realBufferBindingToVirtual[attrib.m_bufferBinding] = inf.m_vertexBufferBindingCount;
  70. ++inf.m_vertexBufferBindingCount;
  71. }
  72. // Change the binding of the attrib
  73. attrib.m_bufferBinding = realBufferBindingToVirtual[attrib.m_bufferBinding];
  74. }
  75. ANKI_ASSERT(inf.m_vertexAttributeCount != 0 && inf.m_vertexBufferBindingCount != 0);
  76. }
  77. // Index buff
  78. U32 indexCount;
  79. mesh.getIndexBufferInfo(inf.m_indexBuffer, inf.m_indexBufferOffset, indexCount, inf.m_indexType);
  80. // Other
  81. ANKI_ASSERT(subMeshIndicesArray.getSize() == 0 && mesh.getSubMeshCount() == 1 && "Not supported ATM");
  82. inf.m_drawcallCount = 1;
  83. inf.m_indicesOffsetArray[0] = 0;
  84. inf.m_indicesCountArray[0] = indexCount;
  85. }
  86. void ModelPatch::getRayTracingInfo(U32 lod, ModelRayTracingInfo& info) const
  87. {
  88. ANKI_ASSERT(m_mtl->getSupportedRayTracingTypes() != RayTypeBit::NONE);
  89. info.m_grObjectReferenceCount = 0;
  90. memset(&info.m_descriptor, 0, sizeof(info.m_descriptor));
  91. // Mesh
  92. const MeshResourcePtr& mesh = m_meshes[min(U32(m_meshCount - 1), lod)];
  93. info.m_bottomLevelAccelerationStructure = mesh->getBottomLevelAccelerationStructure();
  94. info.m_descriptor.m_mesh = mesh->getMeshGpuDescriptor();
  95. info.m_grObjectReferences[info.m_grObjectReferenceCount++] = mesh->getIndexBuffer();
  96. info.m_grObjectReferences[info.m_grObjectReferenceCount++] = mesh->getVertexBuffer();
  97. // Material
  98. info.m_descriptor.m_material = m_mtl->getMaterialGpuDescriptor();
  99. for(RayType rayType : EnumIterable<RayType>())
  100. {
  101. if(!!(m_mtl->getSupportedRayTracingTypes() & RayTypeBit(1 << rayType)))
  102. {
  103. info.m_shaderGroupHandles[rayType] = m_mtl->getShaderGroupHandle(rayType);
  104. }
  105. }
  106. ConstWeakArray<TextureViewPtr> textureViews = m_mtl->getAllTextureViews();
  107. for(U32 i = 0; i < textureViews.getSize(); ++i)
  108. {
  109. info.m_grObjectReferences[info.m_grObjectReferenceCount++] = textureViews[i];
  110. }
  111. }
  112. U32 ModelPatch::getLodCount() const
  113. {
  114. return max<U32>(m_meshCount, getMaterial()->getLodCount());
  115. }
  116. Error ModelPatch::init(ModelResource* model, ConstWeakArray<CString> meshFNames, const CString& mtlFName, Bool async,
  117. ResourceManager* manager)
  118. {
  119. ANKI_ASSERT(meshFNames.getSize() > 0);
  120. m_model = model;
  121. // Load material
  122. ANKI_CHECK(manager->loadResource(mtlFName, m_mtl, async));
  123. // Load meshes
  124. m_meshCount = 0;
  125. for(U32 i = 0; i < meshFNames.getSize(); i++)
  126. {
  127. ANKI_CHECK(manager->loadResource(meshFNames[i], m_meshes[i], async));
  128. // Sanity check
  129. if(i > 0 && !m_meshes[i]->isCompatible(*m_meshes[i - 1]))
  130. {
  131. ANKI_RESOURCE_LOGE("Meshes not compatible");
  132. return Error::USER_DATA;
  133. }
  134. ++m_meshCount;
  135. }
  136. return Error::NONE;
  137. }
  138. ModelResource::ModelResource(ResourceManager* manager)
  139. : ResourceObject(manager)
  140. {
  141. }
  142. ModelResource::~ModelResource()
  143. {
  144. auto alloc = getAllocator();
  145. m_modelPatches.destroy(alloc);
  146. }
  147. Error ModelResource::load(const ResourceFilename& filename, Bool async)
  148. {
  149. auto alloc = getAllocator();
  150. // Load
  151. //
  152. XmlElement el;
  153. XmlDocument doc;
  154. ANKI_CHECK(openFileParseXml(filename, doc));
  155. XmlElement rootEl;
  156. ANKI_CHECK(doc.getChildElement("model", rootEl));
  157. // <modelPatches>
  158. XmlElement modelPatchesEl;
  159. ANKI_CHECK(rootEl.getChildElement("modelPatches", modelPatchesEl));
  160. XmlElement modelPatchEl;
  161. ANKI_CHECK(modelPatchesEl.getChildElement("modelPatch", modelPatchEl));
  162. // Count
  163. U32 count = 0;
  164. do
  165. {
  166. ++count;
  167. // Move to next
  168. ANKI_CHECK(modelPatchEl.getNextSiblingElement("modelPatch", modelPatchEl));
  169. } while(modelPatchEl);
  170. // Check number of model patches
  171. if(count < 1)
  172. {
  173. ANKI_RESOURCE_LOGE("Zero number of model patches");
  174. return Error::USER_DATA;
  175. }
  176. m_modelPatches.create(alloc, count);
  177. count = 0;
  178. ANKI_CHECK(modelPatchesEl.getChildElement("modelPatch", modelPatchEl));
  179. do
  180. {
  181. XmlElement materialEl;
  182. ANKI_CHECK(modelPatchEl.getChildElement("material", materialEl));
  183. Array<CString, 3> meshesFnames;
  184. U32 meshesCount = 1;
  185. // Get mesh
  186. XmlElement meshEl;
  187. ANKI_CHECK(modelPatchEl.getChildElement("mesh", meshEl));
  188. XmlElement meshEl1;
  189. ANKI_CHECK(modelPatchEl.getChildElementOptional("mesh1", meshEl1));
  190. XmlElement meshEl2;
  191. ANKI_CHECK(modelPatchEl.getChildElementOptional("mesh2", meshEl2));
  192. ANKI_CHECK(meshEl.getText(meshesFnames[0]));
  193. if(meshEl1)
  194. {
  195. ++meshesCount;
  196. ANKI_CHECK(meshEl1.getText(meshesFnames[1]));
  197. }
  198. if(meshEl2)
  199. {
  200. ++meshesCount;
  201. ANKI_CHECK(meshEl2.getText(meshesFnames[2]));
  202. }
  203. CString cstr;
  204. ANKI_CHECK(materialEl.getText(cstr));
  205. ANKI_CHECK(m_modelPatches[count].init(this, ConstWeakArray<CString>(&meshesFnames[0], meshesCount), cstr, async,
  206. &getManager()));
  207. // Move to next
  208. ANKI_CHECK(modelPatchEl.getNextSiblingElement("modelPatch", modelPatchEl));
  209. } while(modelPatchEl);
  210. // <skeleton>
  211. XmlElement skeletonEl;
  212. ANKI_CHECK(rootEl.getChildElementOptional("skeleton", skeletonEl));
  213. if(skeletonEl)
  214. {
  215. CString fname;
  216. ANKI_CHECK(skeletonEl.getText(fname));
  217. ANKI_CHECK(getManager().loadResource(fname, m_skeleton));
  218. }
  219. // Calculate compound bounding volume
  220. RenderingKey key;
  221. key.setLod(0);
  222. m_visibilityShape = m_modelPatches[0].getMesh(key).getBoundingShape();
  223. for(auto it = m_modelPatches.getBegin() + 1; it != m_modelPatches.getEnd(); ++it)
  224. {
  225. m_visibilityShape = m_visibilityShape.getCompoundShape((*it).getMesh(key).getBoundingShape());
  226. }
  227. return Error::NONE;
  228. }
  229. } // end namespace anki