ModelNode.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  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/scene/ModelNode.h>
  6. #include <anki/scene/SceneGraph.h>
  7. #include <anki/scene/DebugDrawer.h>
  8. #include <anki/scene/components/BodyComponent.h>
  9. #include <anki/scene/components/SkinComponent.h>
  10. #include <anki/scene/components/RenderComponent.h>
  11. #include <anki/resource/ModelResource.h>
  12. #include <anki/resource/ResourceManager.h>
  13. #include <anki/resource/SkeletonResource.h>
  14. #include <anki/physics/PhysicsWorld.h>
  15. namespace anki
  16. {
  17. /// Feedback component.
  18. class ModelNode::MoveFeedbackComponent : public SceneComponent
  19. {
  20. public:
  21. MoveFeedbackComponent()
  22. : SceneComponent(SceneComponentType::NONE)
  23. {
  24. }
  25. ANKI_USE_RESULT Error update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated) override
  26. {
  27. updated = false;
  28. const MoveComponent& move = node.getFirstComponentOfType<MoveComponent>();
  29. const SkinComponent* skin = node.tryGetFirstComponentOfType<SkinComponent>();
  30. if(move.getTimestamp() == node.getGlobalTimestamp()
  31. || (skin && skin->getTimestamp() == node.getGlobalTimestamp()))
  32. {
  33. ModelNode& mnode = static_cast<ModelNode&>(node);
  34. mnode.updateSpatialComponent(move);
  35. }
  36. return Error::NONE;
  37. }
  38. };
  39. /// Feedback component.
  40. class ModelNode::SkinFeedbackComponent : public SceneComponent
  41. {
  42. public:
  43. SkinFeedbackComponent()
  44. : SceneComponent(SceneComponentType::NONE)
  45. {
  46. }
  47. ANKI_USE_RESULT Error update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated) override
  48. {
  49. updated = false;
  50. const SkinComponent& skin = node.getFirstComponentOfType<SkinComponent>();
  51. if(skin.getTimestamp() == node.getGlobalTimestamp())
  52. {
  53. ModelNode& mnode = static_cast<ModelNode&>(node);
  54. const Aabb& box = skin.getBoneBoundingVolume();
  55. mnode.m_obbLocal.setCenter((box.getMin() + box.getMax()) / 2.0f);
  56. mnode.m_obbLocal.setExtend(box.getMax() - mnode.m_obbLocal.getCenter());
  57. mnode.m_obbLocal.setRotation(Mat3x4::getIdentity());
  58. }
  59. return Error::NONE;
  60. }
  61. };
  62. ModelNode::ModelNode(SceneGraph* scene, CString name)
  63. : SceneNode(scene, name)
  64. {
  65. }
  66. ModelNode::~ModelNode()
  67. {
  68. }
  69. Error ModelNode::init(ModelResourcePtr resource, U32 modelPatchIdx)
  70. {
  71. ANKI_ASSERT(modelPatchIdx < resource->getModelPatches().getSize());
  72. ANKI_CHECK(m_dbgDrawer.init(&getResourceManager()));
  73. m_model = resource;
  74. m_modelPatchIdx = modelPatchIdx;
  75. // Merge key
  76. Array<U64, 2> toHash;
  77. toHash[0] = modelPatchIdx;
  78. toHash[1] = resource->getUuid();
  79. m_mergeKey = computeHash(&toHash[0], sizeof(toHash));
  80. // Components
  81. if(m_model->getSkeleton().isCreated())
  82. {
  83. newComponent<SkinComponent>(this, m_model->getSkeleton());
  84. newComponent<SkinFeedbackComponent>();
  85. }
  86. newComponent<MoveComponent>();
  87. newComponent<MoveFeedbackComponent>();
  88. newComponent<SpatialComponent>(this, &m_obbWorld);
  89. RenderComponent* rcomp = newComponent<RenderComponent>();
  90. rcomp->setupRaster(
  91. [](RenderQueueDrawContext& ctx, ConstWeakArray<void*> userData) {
  92. const ModelNode& self = *static_cast<const ModelNode*>(userData[0]);
  93. self.draw(ctx, userData);
  94. },
  95. this, m_mergeKey);
  96. rcomp->setFlagsFromMaterial(m_model->getModelPatches()[m_modelPatchIdx].getMaterial());
  97. m_obbLocal = m_model->getModelPatches()[m_modelPatchIdx].getBoundingShape();
  98. return Error::NONE;
  99. }
  100. Error ModelNode::init(const CString& modelFname)
  101. {
  102. ModelResourcePtr model;
  103. ANKI_CHECK(getResourceManager().loadResource(modelFname, model));
  104. // Init this
  105. ANKI_CHECK(init(model, 0));
  106. // Create separate nodes for the model patches and make the children
  107. for(U32 i = 1; i < model->getModelPatches().getSize(); ++i)
  108. {
  109. ModelNode* other;
  110. ANKI_CHECK(getSceneGraph().newSceneNode(CString(), other, model, i));
  111. addChild(other);
  112. }
  113. return Error::NONE;
  114. }
  115. void ModelNode::updateSpatialComponent(const MoveComponent& move)
  116. {
  117. m_obbWorld = m_obbLocal.getTransformed(move.getWorldTransform());
  118. SpatialComponent& sp = getFirstComponentOfType<SpatialComponent>();
  119. sp.markForUpdate();
  120. sp.setSpatialOrigin(move.getWorldTransform().getOrigin());
  121. }
  122. void ModelNode::draw(RenderQueueDrawContext& ctx, ConstWeakArray<void*> userData) const
  123. {
  124. ANKI_ASSERT(userData.getSize() > 0 && userData.getSize() <= MAX_INSTANCES);
  125. ANKI_ASSERT(ctx.m_key.getInstanceCount() == userData.getSize());
  126. CommandBufferPtr& cmdb = ctx.m_commandBuffer;
  127. if(ANKI_LIKELY(!ctx.m_debugDraw))
  128. {
  129. const ModelPatch& patch = m_model->getModelPatches()[m_modelPatchIdx];
  130. // That will not work on multi-draw and instanced at the same time. Make sure that there is no multi-draw
  131. // anywhere
  132. ANKI_ASSERT(patch.getSubMeshCount() == 1);
  133. // Transforms
  134. Array<Mat4, MAX_INSTANCES> trfs;
  135. Array<Mat4, MAX_INSTANCES> prevTrfs;
  136. const MoveComponent& movec = getFirstComponentOfType<MoveComponent>();
  137. trfs[0] = Mat4(movec.getWorldTransform());
  138. prevTrfs[0] = Mat4(movec.getPreviousWorldTransform());
  139. Bool moved = trfs[0] != prevTrfs[0];
  140. for(U32 i = 1; i < userData.getSize(); ++i)
  141. {
  142. const ModelNode& self2 = *static_cast<const ModelNode*>(userData[i]);
  143. const MoveComponent& movec = self2.getFirstComponentOfType<MoveComponent>();
  144. trfs[i] = Mat4(movec.getWorldTransform());
  145. prevTrfs[i] = Mat4(movec.getPreviousWorldTransform());
  146. moved = moved || (trfs[i] != prevTrfs[i]);
  147. }
  148. ctx.m_key.setVelocity(moved && ctx.m_key.getPass() == Pass::GB);
  149. ModelRenderingInfo modelInf;
  150. patch.getRenderingInfo(ctx.m_key, WeakArray<U8>(), modelInf);
  151. // Bones storage
  152. if(m_model->getSkeleton())
  153. {
  154. const SkinComponent& skinc = getComponentAt<SkinComponent>(0);
  155. const U32 boneCount = skinc.getBoneTransforms().getSize();
  156. StagingGpuMemoryToken token, tokenPrev;
  157. void* trfs = ctx.m_stagingGpuAllocator->allocateFrame(boneCount * sizeof(Mat4),
  158. StagingGpuMemoryType::STORAGE, token);
  159. memcpy(trfs, &skinc.getBoneTransforms()[0], boneCount * sizeof(Mat4));
  160. trfs = ctx.m_stagingGpuAllocator->allocateFrame(boneCount * sizeof(Mat4), StagingGpuMemoryType::STORAGE,
  161. tokenPrev);
  162. memcpy(trfs, &skinc.getPreviousFrameBoneTransforms()[0], boneCount * sizeof(Mat4));
  163. ANKI_ASSERT(modelInf.m_boneTransformsBinding < MAX_U32);
  164. cmdb->bindStorageBuffer(patch.getMaterial()->getDescriptorSetIndex(), modelInf.m_boneTransformsBinding,
  165. token.m_buffer, token.m_offset, token.m_range);
  166. ANKI_ASSERT(modelInf.m_prevFrameBoneTransformsBinding < MAX_U32);
  167. cmdb->bindStorageBuffer(patch.getMaterial()->getDescriptorSetIndex(),
  168. modelInf.m_prevFrameBoneTransformsBinding, tokenPrev.m_buffer, tokenPrev.m_offset,
  169. tokenPrev.m_range);
  170. }
  171. // Program
  172. cmdb->bindShaderProgram(modelInf.m_program);
  173. // Uniforms
  174. RenderComponent::allocateAndSetupUniforms(m_model->getModelPatches()[m_modelPatchIdx].getMaterial(), ctx,
  175. ConstWeakArray<Mat4>(&trfs[0], userData.getSize()),
  176. ConstWeakArray<Mat4>(&prevTrfs[0], userData.getSize()),
  177. *ctx.m_stagingGpuAllocator);
  178. // Set attributes
  179. for(U i = 0; i < modelInf.m_vertexAttributeCount; ++i)
  180. {
  181. const VertexAttributeInfo& attrib = modelInf.m_vertexAttributes[i];
  182. ANKI_ASSERT(attrib.m_format != Format::NONE);
  183. cmdb->setVertexAttribute(U32(attrib.m_location), attrib.m_bufferBinding, attrib.m_format,
  184. attrib.m_relativeOffset);
  185. }
  186. // Set vertex buffers
  187. for(U32 i = 0; i < modelInf.m_vertexBufferBindingCount; ++i)
  188. {
  189. const VertexBufferBinding& binding = modelInf.m_vertexBufferBindings[i];
  190. cmdb->bindVertexBuffer(i, binding.m_buffer, binding.m_offset, binding.m_stride, VertexStepRate::VERTEX);
  191. }
  192. // Index buffer
  193. cmdb->bindIndexBuffer(modelInf.m_indexBuffer, 0, IndexType::U16);
  194. // Draw
  195. cmdb->drawElements(PrimitiveTopology::TRIANGLES, modelInf.m_indicesCountArray[0], userData.getSize(),
  196. U32(modelInf.m_indicesOffsetArray[0] / sizeof(U16)), 0, 0);
  197. }
  198. else
  199. {
  200. // Draw the bounding volumes
  201. Mat4* const mvps = ctx.m_frameAllocator.newArray<Mat4>(userData.getSize());
  202. for(U32 i = 0; i < userData.getSize(); ++i)
  203. {
  204. const ModelNode& self2 = *static_cast<const ModelNode*>(userData[i]);
  205. const Mat3 rot = self2.m_obbWorld.getRotation().getRotationPart();
  206. const Vec4 tsl = self2.m_obbWorld.getCenter().xyz1();
  207. const Vec3 scale = self2.m_obbWorld.getExtend().xyz();
  208. // Set non uniform scale. Add a margin to avoid flickering
  209. Mat3 nonUniScale = Mat3::getZero();
  210. constexpr F32 MARGIN = 1.02f;
  211. nonUniScale(0, 0) = scale.x() * MARGIN;
  212. nonUniScale(1, 1) = scale.y() * MARGIN;
  213. nonUniScale(2, 2) = scale.z() * MARGIN;
  214. mvps[i] = ctx.m_viewProjectionMatrix * Mat4(tsl, rot * nonUniScale, 1.0f);
  215. }
  216. const Bool enableDepthTest = ctx.m_debugDrawFlags.get(RenderQueueDebugDrawFlag::DEPTH_TEST_ON);
  217. if(enableDepthTest)
  218. {
  219. cmdb->setDepthCompareOperation(CompareOperation::LESS);
  220. }
  221. else
  222. {
  223. cmdb->setDepthCompareOperation(CompareOperation::ALWAYS);
  224. }
  225. m_dbgDrawer.drawCubes(ConstWeakArray<Mat4>(mvps, userData.getSize()), Vec4(1.0f, 0.0f, 1.0f, 1.0f), 2.0f,
  226. ctx.m_debugDrawFlags.get(RenderQueueDebugDrawFlag::DITHERED_DEPTH_TEST_ON), 2.0f,
  227. *ctx.m_stagingGpuAllocator, cmdb);
  228. ctx.m_frameAllocator.deleteArray(mvps, userData.getSize());
  229. // Bones
  230. if(m_model->getSkeleton())
  231. {
  232. const SkinComponent& skinc = getComponentAt<SkinComponent>(0);
  233. SkeletonResourcePtr skeleton = skinc.getSkeleronResource();
  234. const U32 boneCount = skinc.getBoneTransforms().getSize();
  235. DynamicArrayAuto<Vec3> lines(ctx.m_frameAllocator);
  236. lines.resizeStorage(boneCount * 2);
  237. DynamicArrayAuto<Vec3> chidlessLines(ctx.m_frameAllocator);
  238. for(U32 i = 0; i < boneCount; ++i)
  239. {
  240. const Bone& bone = skeleton->getBones()[i];
  241. ANKI_ASSERT(bone.getIndex() == i);
  242. const Vec4 point(0.0f, 0.0f, 0.0f, 1.0f);
  243. const Bone* parent = bone.getParent();
  244. Mat4 m = (parent)
  245. ? skinc.getBoneTransforms()[parent->getIndex()] * parent->getVertexTransform().getInverse()
  246. : Mat4::getIdentity();
  247. const Vec3 a = (m * point).xyz();
  248. m = skinc.getBoneTransforms()[i] * bone.getVertexTransform().getInverse();
  249. const Vec3 b = (m * point).xyz();
  250. lines.emplaceBack(a);
  251. lines.emplaceBack(b);
  252. if(bone.getChildren().getSize() == 0)
  253. {
  254. // If there are not children try to draw something for that bone as well
  255. chidlessLines.emplaceBack(b);
  256. const F32 len = (b - a).getLength();
  257. const Vec3 c = b + (b - a).getNormalized() * len;
  258. chidlessLines.emplaceBack(c);
  259. }
  260. }
  261. const Mat4 mvp =
  262. ctx.m_viewProjectionMatrix * Mat4(getFirstComponentOfType<MoveComponent>().getWorldTransform());
  263. m_dbgDrawer.drawLines(ConstWeakArray<Mat4>(&mvp, 1), Vec4(1.0f), 20.0f,
  264. ctx.m_debugDrawFlags.get(RenderQueueDebugDrawFlag::DITHERED_DEPTH_TEST_ON), lines,
  265. *ctx.m_stagingGpuAllocator, cmdb);
  266. m_dbgDrawer.drawLines(ConstWeakArray<Mat4>(&mvp, 1), Vec4(0.7f, 0.7f, 0.7f, 1.0f), 5.0f,
  267. ctx.m_debugDrawFlags.get(RenderQueueDebugDrawFlag::DITHERED_DEPTH_TEST_ON),
  268. chidlessLines, *ctx.m_stagingGpuAllocator, cmdb);
  269. }
  270. // Restore state
  271. if(!enableDepthTest)
  272. {
  273. cmdb->setDepthCompareOperation(CompareOperation::LESS);
  274. }
  275. }
  276. }
  277. } // end namespace anki