ModelResource.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. // Copyright (C) 2009-2022, 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. static Bool attributeIsRequired(VertexAttributeId loc, RenderingTechnique technique, Bool hasSkin)
  12. {
  13. if(technique == RenderingTechnique::GBUFFER || technique == RenderingTechnique::FORWARD)
  14. {
  15. return true;
  16. }
  17. else if(!hasSkin)
  18. {
  19. return loc == VertexAttributeId::POSITION || loc == VertexAttributeId::UV0;
  20. }
  21. else
  22. {
  23. return loc == VertexAttributeId::POSITION || loc == VertexAttributeId::BONE_INDICES
  24. || loc == VertexAttributeId::BONE_WEIGHTS || loc == VertexAttributeId::UV0;
  25. }
  26. }
  27. void ModelPatch::getRenderingInfo(const RenderingKey& key, ModelRenderingInfo& inf) const
  28. {
  29. ANKI_ASSERT(!(!supportsSkinning() && key.getSkinned()));
  30. const U32 meshLod = min<U32>(key.getLod(), m_meshLodCount - 1);
  31. // Vertex attributes & bindings
  32. {
  33. U32 bufferBindingVisitedMask = 0;
  34. Array<U32, MAX_VERTEX_ATTRIBUTES> realBufferBindingToVirtual;
  35. inf.m_vertexAttributeCount = 0;
  36. inf.m_vertexBufferBindingCount = 0;
  37. for(VertexAttributeId loc : EnumIterable<VertexAttributeId>())
  38. {
  39. if(!m_presentVertexAttributes.get(loc)
  40. || !attributeIsRequired(loc, key.getRenderingTechnique(), key.getSkinned()))
  41. {
  42. continue;
  43. }
  44. // Attribute
  45. ModelVertexAttribute& outAttribInfo = inf.m_vertexAttributes[inf.m_vertexAttributeCount++];
  46. outAttribInfo.m_location = loc;
  47. outAttribInfo.m_bufferBinding = m_vertexAttributeInfos[loc].m_bufferBinding;
  48. outAttribInfo.m_relativeOffset = m_vertexAttributeInfos[loc].m_relativeOffset;
  49. outAttribInfo.m_format = m_vertexAttributeInfos[loc].m_format;
  50. // Binding. Also, remove any holes in the bindings
  51. if(!(bufferBindingVisitedMask & (1 << outAttribInfo.m_bufferBinding)))
  52. {
  53. bufferBindingVisitedMask |= 1 << outAttribInfo.m_bufferBinding;
  54. ModelVertexBufferBinding& outBinding = inf.m_vertexBufferBindings[inf.m_vertexBufferBindingCount];
  55. const VertexBufferInfo& inBinding = m_vertexBufferInfos[meshLod][outAttribInfo.m_bufferBinding];
  56. outBinding.m_buffer = inBinding.m_buffer;
  57. ANKI_ASSERT(outBinding.m_buffer.isCreated());
  58. outBinding.m_offset = inBinding.m_offset;
  59. ANKI_ASSERT(outBinding.m_offset != MAX_PTR_SIZE);
  60. outBinding.m_stride = inBinding.m_stride;
  61. ANKI_ASSERT(outBinding.m_stride != MAX_PTR_SIZE);
  62. realBufferBindingToVirtual[outAttribInfo.m_bufferBinding] = inf.m_vertexBufferBindingCount;
  63. ++inf.m_vertexBufferBindingCount;
  64. }
  65. // Change the binding of the attrib
  66. outAttribInfo.m_bufferBinding = realBufferBindingToVirtual[outAttribInfo.m_bufferBinding];
  67. }
  68. ANKI_ASSERT(inf.m_vertexAttributeCount != 0 && inf.m_vertexBufferBindingCount != 0);
  69. }
  70. // Index buff
  71. inf.m_indexBuffer = m_indexBufferInfos[meshLod].m_buffer;
  72. inf.m_indexBufferOffset = m_indexBufferInfos[meshLod].m_offset;
  73. inf.m_indexCount = m_indexBufferInfos[meshLod].m_indexCount;
  74. inf.m_firstIndex = m_indexBufferInfos[meshLod].m_firstIndex;
  75. inf.m_indexType = m_indexType;
  76. // Get program
  77. const MaterialVariant& variant = m_mtl->getOrCreateVariant(key);
  78. inf.m_program = variant.getShaderProgram();
  79. }
  80. void ModelPatch::getRayTracingInfo(const RenderingKey& key, ModelRayTracingInfo& info) const
  81. {
  82. ANKI_ASSERT(!!(m_mtl->getRenderingTechniques() & RenderingTechniqueBit(1 << key.getRenderingTechnique())));
  83. // Mesh
  84. const MeshResourcePtr& mesh = m_meshes[min(U32(m_meshLodCount - 1), key.getLod())];
  85. info.m_bottomLevelAccelerationStructure = mesh->getBottomLevelAccelerationStructure();
  86. // Material
  87. const MaterialVariant& variant = m_mtl->getOrCreateVariant(key);
  88. info.m_shaderGroupHandleIndex = variant.getRtShaderGroupHandleIndex();
  89. // Misc
  90. info.m_grObjectReferences = m_grObjectRefs;
  91. }
  92. Error ModelPatch::init(ModelResource* model, ConstWeakArray<CString> meshFNames, const CString& mtlFName,
  93. U32 subMeshIndex, Bool async, ResourceManager* manager)
  94. {
  95. ANKI_ASSERT(meshFNames.getSize() > 0);
  96. #if ANKI_ENABLE_ASSERTIONS
  97. m_model = model;
  98. #endif
  99. // Load material
  100. ANKI_CHECK(manager->loadResource(mtlFName, m_mtl, async));
  101. // Gather the material refs
  102. if(m_mtl->getAllTextures().getSize())
  103. {
  104. m_grObjectRefs.resizeStorage(model->getAllocator(), m_mtl->getAllTextures().getSize());
  105. for(U32 i = 0; i < m_mtl->getAllTextures().getSize(); ++i)
  106. {
  107. m_grObjectRefs.emplaceBack(model->getAllocator(), m_mtl->getAllTextures()[i]);
  108. }
  109. }
  110. // Load meshes
  111. m_meshLodCount = 0;
  112. for(U32 lod = 0; lod < meshFNames.getSize(); lod++)
  113. {
  114. ANKI_CHECK(manager->loadResource(meshFNames[lod], m_meshes[lod], async));
  115. // Sanity check
  116. if(lod > 0 && !m_meshes[lod]->isCompatible(*m_meshes[lod - 1]))
  117. {
  118. ANKI_RESOURCE_LOGE("Meshes not compatible");
  119. return Error::USER_DATA;
  120. }
  121. // Submesh index
  122. if(subMeshIndex != MAX_U32 && subMeshIndex >= m_meshes[lod]->getSubMeshCount())
  123. {
  124. ANKI_RESOURCE_LOGE("Wrong subMeshIndex given");
  125. return Error::USER_DATA;
  126. }
  127. ++m_meshLodCount;
  128. }
  129. // Create the cached items
  130. {
  131. // Vertex attributes
  132. for(VertexAttributeId attrib : EnumIterable<VertexAttributeId>())
  133. {
  134. const MeshResource& mesh = *m_meshes[0].get();
  135. const Bool enabled = mesh.isVertexAttributePresent(attrib);
  136. m_presentVertexAttributes.set(U32(attrib), enabled);
  137. if(!enabled)
  138. {
  139. continue;
  140. }
  141. VertexAttributeInfo& outAttribInfo = m_vertexAttributeInfos[attrib];
  142. U32 bufferBinding, relativeOffset;
  143. mesh.getVertexAttributeInfo(attrib, bufferBinding, outAttribInfo.m_format, relativeOffset);
  144. outAttribInfo.m_bufferBinding = bufferBinding & 0xFu;
  145. outAttribInfo.m_relativeOffset = relativeOffset & 0xFFFFFFu;
  146. }
  147. // Vertex buffers
  148. for(U32 lod = 0; lod < m_meshLodCount; ++lod)
  149. {
  150. const MeshResource& mesh = *m_meshes[lod].get();
  151. for(VertexAttributeId attrib : EnumIterable<VertexAttributeId>())
  152. {
  153. if(!m_presentVertexAttributes.get(attrib))
  154. {
  155. continue;
  156. }
  157. VertexBufferInfo& outVertBufferInfo =
  158. m_vertexBufferInfos[lod][m_vertexAttributeInfos[attrib].m_bufferBinding];
  159. if(!outVertBufferInfo.m_buffer.isCreated())
  160. {
  161. PtrSize offset, stride;
  162. mesh.getVertexBufferInfo(m_vertexAttributeInfos[attrib].m_bufferBinding, outVertBufferInfo.m_buffer,
  163. offset, stride);
  164. outVertBufferInfo.m_offset = offset & 0xFFFFFFFFFFFF;
  165. outVertBufferInfo.m_stride = stride & 0xFFFF;
  166. }
  167. }
  168. }
  169. // Index buffer
  170. for(U32 lod = 0; lod < m_meshLodCount; ++lod)
  171. {
  172. const MeshResource& mesh = *m_meshes[lod].get();
  173. IndexBufferInfo& outIndexBufferInfo = m_indexBufferInfos[lod];
  174. if(subMeshIndex == MAX_U32)
  175. {
  176. IndexType indexType;
  177. PtrSize offset;
  178. mesh.getIndexBufferInfo(outIndexBufferInfo.m_buffer, offset, outIndexBufferInfo.m_indexCount,
  179. indexType);
  180. outIndexBufferInfo.m_offset = offset;
  181. outIndexBufferInfo.m_firstIndex = 0;
  182. m_indexType = indexType;
  183. }
  184. else
  185. {
  186. IndexType indexType;
  187. PtrSize offset;
  188. mesh.getIndexBufferInfo(outIndexBufferInfo.m_buffer, offset, outIndexBufferInfo.m_indexCount,
  189. indexType);
  190. outIndexBufferInfo.m_offset = offset;
  191. m_indexType = indexType;
  192. Aabb aabb;
  193. mesh.getSubMeshInfo(subMeshIndex, outIndexBufferInfo.m_firstIndex, outIndexBufferInfo.m_indexCount,
  194. aabb);
  195. }
  196. }
  197. }
  198. return Error::NONE;
  199. }
  200. ModelResource::ModelResource(ResourceManager* manager)
  201. : ResourceObject(manager)
  202. {
  203. }
  204. ModelResource::~ModelResource()
  205. {
  206. auto alloc = getAllocator();
  207. for(ModelPatch& patch : m_modelPatches)
  208. {
  209. patch.m_grObjectRefs.destroy(alloc);
  210. }
  211. m_modelPatches.destroy(alloc);
  212. }
  213. Error ModelResource::load(const ResourceFilename& filename, Bool async)
  214. {
  215. auto alloc = getAllocator();
  216. // Load
  217. //
  218. XmlElement el;
  219. XmlDocument doc;
  220. ANKI_CHECK(openFileParseXml(filename, doc));
  221. XmlElement rootEl;
  222. ANKI_CHECK(doc.getChildElement("model", rootEl));
  223. // <modelPatches>
  224. XmlElement modelPatchesEl;
  225. ANKI_CHECK(rootEl.getChildElement("modelPatches", modelPatchesEl));
  226. XmlElement modelPatchEl;
  227. ANKI_CHECK(modelPatchesEl.getChildElement("modelPatch", modelPatchEl));
  228. // Count
  229. U32 count = 0;
  230. do
  231. {
  232. ++count;
  233. // Move to next
  234. ANKI_CHECK(modelPatchEl.getNextSiblingElement("modelPatch", modelPatchEl));
  235. } while(modelPatchEl);
  236. // Check number of model patches
  237. if(count < 1)
  238. {
  239. ANKI_RESOURCE_LOGE("Zero number of model patches");
  240. return Error::USER_DATA;
  241. }
  242. m_modelPatches.create(alloc, count);
  243. count = 0;
  244. ANKI_CHECK(modelPatchesEl.getChildElement("modelPatch", modelPatchEl));
  245. do
  246. {
  247. U32 subMeshIndex;
  248. Bool subMeshIndexPresent;
  249. ANKI_CHECK(modelPatchEl.getAttributeNumberOptional("subMeshIndex", subMeshIndex, subMeshIndexPresent));
  250. if(!subMeshIndexPresent)
  251. {
  252. subMeshIndex = MAX_U32;
  253. }
  254. XmlElement materialEl;
  255. ANKI_CHECK(modelPatchEl.getChildElement("material", materialEl));
  256. Array<CString, 3> meshesFnames;
  257. U32 meshesCount = 1;
  258. XmlElement meshEl;
  259. ANKI_CHECK(modelPatchEl.getChildElement("mesh", meshEl));
  260. XmlElement meshEl1;
  261. ANKI_CHECK(modelPatchEl.getChildElementOptional("mesh1", meshEl1));
  262. XmlElement meshEl2;
  263. ANKI_CHECK(modelPatchEl.getChildElementOptional("mesh2", meshEl2));
  264. ANKI_CHECK(meshEl.getText(meshesFnames[0]));
  265. if(meshEl1)
  266. {
  267. ++meshesCount;
  268. ANKI_CHECK(meshEl1.getText(meshesFnames[1]));
  269. }
  270. if(meshEl2)
  271. {
  272. ++meshesCount;
  273. ANKI_CHECK(meshEl2.getText(meshesFnames[2]));
  274. }
  275. CString cstr;
  276. ANKI_CHECK(materialEl.getText(cstr));
  277. ANKI_CHECK(m_modelPatches[count].init(this, ConstWeakArray<CString>(&meshesFnames[0], meshesCount), cstr,
  278. subMeshIndex, async, &getManager()));
  279. if(count > 0 && m_modelPatches[count].supportsSkinning() != m_modelPatches[count - 1].supportsSkinning())
  280. {
  281. ANKI_RESOURCE_LOGE("All model patches should support skinning or all shouldn't support skinning");
  282. return Error::USER_DATA;
  283. }
  284. // Move to next
  285. ANKI_CHECK(modelPatchEl.getNextSiblingElement("modelPatch", modelPatchEl));
  286. ++count;
  287. } while(modelPatchEl);
  288. ANKI_ASSERT(count == m_modelPatches.getSize());
  289. // Calculate compound bounding volume
  290. m_boundingVolume = m_modelPatches[0].m_meshes[0]->getBoundingShape();
  291. for(auto it = m_modelPatches.getBegin() + 1; it != m_modelPatches.getEnd(); ++it)
  292. {
  293. m_boundingVolume = m_boundingVolume.getCompoundShape((*it).m_meshes[0]->getBoundingShape());
  294. }
  295. return Error::NONE;
  296. }
  297. } // end namespace anki