ModelResource.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  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. Bool ModelPatch::getRayTracingInfo(U32 lod, RayTracingMaterialType type, ModelRayTracingInfo& info) const
  87. {
  88. const Bool supported = m_mtl->getRayTracingTypeSupported(type);
  89. if(!supported)
  90. {
  91. return false;
  92. }
  93. info.m_grObjectReferenceCount = 0;
  94. memset(&info.m_descriptor, 0, sizeof(info.m_descriptor));
  95. // Mesh
  96. const MeshResourcePtr& mesh = m_meshes[min(U32(m_meshCount - 1), lod)];
  97. info.m_bottomLevelAccelerationStructure = mesh->getBottomLevelAccelerationStructure();
  98. info.m_descriptor.m_mesh = mesh->getMeshGpuDescriptor();
  99. info.m_grObjectReferences[info.m_grObjectReferenceCount++] = mesh->getIndexBuffer();
  100. info.m_grObjectReferences[info.m_grObjectReferenceCount++] = mesh->getVertexBuffer();
  101. // Material
  102. const RayTracingMaterialVariant& materialVariant = m_mtl->getRayTracingVariant(lod, type);
  103. info.m_descriptor.m_material = materialVariant.getMaterialGpuDescriptor();
  104. info.m_shaderGroupHandle = materialVariant.getHitShaderGroupHandle();
  105. for(U32 i = 0; i < materialVariant.getTextureViews().getSize(); ++i)
  106. {
  107. info.m_grObjectReferences[info.m_grObjectReferenceCount++] = materialVariant.getTextureViews()[i];
  108. }
  109. return true;
  110. }
  111. U32 ModelPatch::getLodCount() const
  112. {
  113. return max<U32>(m_meshCount, getMaterial()->getLodCount());
  114. }
  115. Error ModelPatch::init(ModelResource* model, ConstWeakArray<CString> meshFNames, const CString& mtlFName, Bool async,
  116. ResourceManager* manager)
  117. {
  118. ANKI_ASSERT(meshFNames.getSize() > 0);
  119. m_model = model;
  120. // Load material
  121. ANKI_CHECK(manager->loadResource(mtlFName, m_mtl, async));
  122. // Load meshes
  123. m_meshCount = 0;
  124. for(U32 i = 0; i < meshFNames.getSize(); i++)
  125. {
  126. ANKI_CHECK(manager->loadResource(meshFNames[i], m_meshes[i], async));
  127. // Sanity check
  128. if(i > 0 && !m_meshes[i]->isCompatible(*m_meshes[i - 1]))
  129. {
  130. ANKI_RESOURCE_LOGE("Meshes not compatible");
  131. return Error::USER_DATA;
  132. }
  133. ++m_meshCount;
  134. }
  135. return Error::NONE;
  136. }
  137. ModelResource::ModelResource(ResourceManager* manager)
  138. : ResourceObject(manager)
  139. {
  140. }
  141. ModelResource::~ModelResource()
  142. {
  143. auto alloc = getAllocator();
  144. m_modelPatches.destroy(alloc);
  145. }
  146. Error ModelResource::load(const ResourceFilename& filename, Bool async)
  147. {
  148. auto alloc = getAllocator();
  149. // Load
  150. //
  151. XmlElement el;
  152. XmlDocument doc;
  153. ANKI_CHECK(openFileParseXml(filename, doc));
  154. XmlElement rootEl;
  155. ANKI_CHECK(doc.getChildElement("model", rootEl));
  156. // <modelPatches>
  157. XmlElement modelPatchesEl;
  158. ANKI_CHECK(rootEl.getChildElement("modelPatches", modelPatchesEl));
  159. XmlElement modelPatchEl;
  160. ANKI_CHECK(modelPatchesEl.getChildElement("modelPatch", modelPatchEl));
  161. // Count
  162. U32 count = 0;
  163. do
  164. {
  165. ++count;
  166. // Move to next
  167. ANKI_CHECK(modelPatchEl.getNextSiblingElement("modelPatch", modelPatchEl));
  168. } while(modelPatchEl);
  169. // Check number of model patches
  170. if(count < 1)
  171. {
  172. ANKI_RESOURCE_LOGE("Zero number of model patches");
  173. return Error::USER_DATA;
  174. }
  175. m_modelPatches.create(alloc, count);
  176. count = 0;
  177. ANKI_CHECK(modelPatchesEl.getChildElement("modelPatch", modelPatchEl));
  178. do
  179. {
  180. XmlElement materialEl;
  181. ANKI_CHECK(modelPatchEl.getChildElement("material", materialEl));
  182. Array<CString, 3> meshesFnames;
  183. U32 meshesCount = 1;
  184. // Get mesh
  185. XmlElement meshEl;
  186. ANKI_CHECK(modelPatchEl.getChildElement("mesh", meshEl));
  187. XmlElement meshEl1;
  188. ANKI_CHECK(modelPatchEl.getChildElementOptional("mesh1", meshEl1));
  189. XmlElement meshEl2;
  190. ANKI_CHECK(modelPatchEl.getChildElementOptional("mesh2", meshEl2));
  191. ANKI_CHECK(meshEl.getText(meshesFnames[0]));
  192. if(meshEl1)
  193. {
  194. ++meshesCount;
  195. ANKI_CHECK(meshEl1.getText(meshesFnames[1]));
  196. }
  197. if(meshEl2)
  198. {
  199. ++meshesCount;
  200. ANKI_CHECK(meshEl2.getText(meshesFnames[2]));
  201. }
  202. CString cstr;
  203. ANKI_CHECK(materialEl.getText(cstr));
  204. ANKI_CHECK(m_modelPatches[count].init(this, ConstWeakArray<CString>(&meshesFnames[0], meshesCount), cstr, async,
  205. &getManager()));
  206. // Move to next
  207. ANKI_CHECK(modelPatchEl.getNextSiblingElement("modelPatch", modelPatchEl));
  208. } while(modelPatchEl);
  209. // <skeleton>
  210. XmlElement skeletonEl;
  211. ANKI_CHECK(rootEl.getChildElementOptional("skeleton", skeletonEl));
  212. if(skeletonEl)
  213. {
  214. CString fname;
  215. ANKI_CHECK(skeletonEl.getText(fname));
  216. ANKI_CHECK(getManager().loadResource(fname, m_skeleton));
  217. }
  218. // Calculate compound bounding volume
  219. RenderingKey key;
  220. key.setLod(0);
  221. m_visibilityShape = m_modelPatches[0].getMesh(key).getBoundingShape();
  222. for(auto it = m_modelPatches.getBegin() + 1; it != m_modelPatches.getEnd(); ++it)
  223. {
  224. m_visibilityShape = m_visibilityShape.getCompoundShape((*it).getMesh(key).getBoundingShape());
  225. }
  226. return Error::NONE;
  227. }
  228. } // end namespace anki