|
@@ -6,9 +6,11 @@
|
|
|
#include <anki/scene/ModelNode.h>
|
|
#include <anki/scene/ModelNode.h>
|
|
|
#include <anki/scene/SceneGraph.h>
|
|
#include <anki/scene/SceneGraph.h>
|
|
|
#include <anki/scene/DebugDrawer.h>
|
|
#include <anki/scene/DebugDrawer.h>
|
|
|
-#include <anki/scene/components/BodyComponent.h>
|
|
|
|
|
|
|
+#include <anki/scene/components/MoveComponent.h>
|
|
|
#include <anki/scene/components/SkinComponent.h>
|
|
#include <anki/scene/components/SkinComponent.h>
|
|
|
|
|
+#include <anki/scene/components/SpatialComponent.h>
|
|
|
#include <anki/scene/components/RenderComponent.h>
|
|
#include <anki/scene/components/RenderComponent.h>
|
|
|
|
|
+#include <anki/scene/components/ModelComponent.h>
|
|
|
#include <anki/resource/ModelResource.h>
|
|
#include <anki/resource/ModelResource.h>
|
|
|
#include <anki/resource/ResourceManager.h>
|
|
#include <anki/resource/ResourceManager.h>
|
|
|
#include <anki/resource/SkeletonResource.h>
|
|
#include <anki/resource/SkeletonResource.h>
|
|
@@ -18,153 +20,154 @@ namespace anki
|
|
|
{
|
|
{
|
|
|
|
|
|
|
|
/// Feedback component.
|
|
/// Feedback component.
|
|
|
-class ModelNode::MoveFeedbackComponent : public SceneComponent
|
|
|
|
|
|
|
+class ModelNode::FeedbackComponent : public SceneComponent
|
|
|
{
|
|
{
|
|
|
|
|
+ ANKI_SCENE_COMPONENT(ModelNode::FeedbackComponent)
|
|
|
|
|
+
|
|
|
public:
|
|
public:
|
|
|
- MoveFeedbackComponent()
|
|
|
|
|
- : SceneComponent(SceneComponentType::NONE)
|
|
|
|
|
|
|
+ FeedbackComponent(SceneNode* node)
|
|
|
|
|
+ : SceneComponent(node, getStaticClassId(), true)
|
|
|
{
|
|
{
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
ANKI_USE_RESULT Error update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated) override
|
|
ANKI_USE_RESULT Error update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated) override
|
|
|
{
|
|
{
|
|
|
updated = false;
|
|
updated = false;
|
|
|
-
|
|
|
|
|
- const MoveComponent& move = node.getFirstComponentOfType<MoveComponent>();
|
|
|
|
|
- const SkinComponent* skin = node.tryGetFirstComponentOfType<SkinComponent>();
|
|
|
|
|
- if(move.getTimestamp() == node.getGlobalTimestamp()
|
|
|
|
|
- || (skin && skin->getTimestamp() == node.getGlobalTimestamp()))
|
|
|
|
|
- {
|
|
|
|
|
- ModelNode& mnode = static_cast<ModelNode&>(node);
|
|
|
|
|
- mnode.updateSpatialComponent(move);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
|
|
+ static_cast<ModelNode&>(node).feedbackUpdate();
|
|
|
return Error::NONE;
|
|
return Error::NONE;
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-/// Feedback component.
|
|
|
|
|
-class ModelNode::SkinFeedbackComponent : public SceneComponent
|
|
|
|
|
|
|
+ANKI_SCENE_COMPONENT_STATICS(ModelNode::FeedbackComponent)
|
|
|
|
|
+
|
|
|
|
|
+class ModelNode::RenderProxy
|
|
|
{
|
|
{
|
|
|
public:
|
|
public:
|
|
|
- SkinFeedbackComponent()
|
|
|
|
|
- : SceneComponent(SceneComponentType::NONE)
|
|
|
|
|
- {
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- ANKI_USE_RESULT Error update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated) override
|
|
|
|
|
- {
|
|
|
|
|
- updated = false;
|
|
|
|
|
-
|
|
|
|
|
- const SkinComponent& skin = node.getFirstComponentOfType<SkinComponent>();
|
|
|
|
|
- if(skin.getTimestamp() == node.getGlobalTimestamp())
|
|
|
|
|
- {
|
|
|
|
|
- ModelNode& mnode = static_cast<ModelNode&>(node);
|
|
|
|
|
-
|
|
|
|
|
- const Aabb& box = skin.getBoneBoundingVolume();
|
|
|
|
|
- mnode.m_obbLocal.setCenter((box.getMin() + box.getMax()) / 2.0f);
|
|
|
|
|
- mnode.m_obbLocal.setExtend(box.getMax() - mnode.m_obbLocal.getCenter());
|
|
|
|
|
- mnode.m_obbLocal.setRotation(Mat3x4::getIdentity());
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return Error::NONE;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ ModelNode* m_node = nullptr;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
ModelNode::ModelNode(SceneGraph* scene, CString name)
|
|
ModelNode::ModelNode(SceneGraph* scene, CString name)
|
|
|
: SceneNode(scene, name)
|
|
: SceneNode(scene, name)
|
|
|
{
|
|
{
|
|
|
|
|
+ newComponent<ModelComponent>();
|
|
|
|
|
+ newComponent<SkinComponent>();
|
|
|
|
|
+ newComponent<MoveComponent>();
|
|
|
|
|
+ newComponent<FeedbackComponent>();
|
|
|
|
|
+ newComponent<SpatialComponent>();
|
|
|
|
|
+ newComponent<RenderComponent>(); // One of many
|
|
|
|
|
+ m_renderProxies.create(getAllocator(), 1);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
ModelNode::~ModelNode()
|
|
ModelNode::~ModelNode()
|
|
|
{
|
|
{
|
|
|
|
|
+ m_renderProxies.destroy(getAllocator());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-Error ModelNode::init(ModelResourcePtr resource, U32 modelPatchIdx)
|
|
|
|
|
|
|
+void ModelNode::feedbackUpdate()
|
|
|
{
|
|
{
|
|
|
- ANKI_ASSERT(modelPatchIdx < resource->getModelPatches().getSize());
|
|
|
|
|
|
|
+ const ModelComponent& modelc = getFirstComponentOfType<ModelComponent>();
|
|
|
|
|
+ const SkinComponent& skinc = getFirstComponentOfType<SkinComponent>();
|
|
|
|
|
+ const MoveComponent& movec = getFirstComponentOfType<MoveComponent>();
|
|
|
|
|
|
|
|
- ANKI_CHECK(m_dbgDrawer.init(&getResourceManager()));
|
|
|
|
|
- m_model = resource;
|
|
|
|
|
- m_modelPatchIdx = modelPatchIdx;
|
|
|
|
|
|
|
+ if(!modelc.isEnabled())
|
|
|
|
|
+ {
|
|
|
|
|
+ // Disable everything
|
|
|
|
|
+ ANKI_ASSERT(!"TODO");
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- // Merge key
|
|
|
|
|
- Array<U64, 2> toHash;
|
|
|
|
|
- toHash[0] = modelPatchIdx;
|
|
|
|
|
- toHash[1] = resource->getUuid();
|
|
|
|
|
- m_mergeKey = computeHash(&toHash[0], sizeof(toHash));
|
|
|
|
|
|
|
+ const U64 globTimestamp = getGlobalTimestamp();
|
|
|
|
|
+ Bool updateSpatial = false;
|
|
|
|
|
|
|
|
- // Components
|
|
|
|
|
- if(m_model->getSkeleton().isCreated())
|
|
|
|
|
|
|
+ // Model update
|
|
|
|
|
+ if(modelc.getTimestamp() == globTimestamp)
|
|
|
{
|
|
{
|
|
|
- newComponent<SkinComponent>(this, m_model->getSkeleton());
|
|
|
|
|
- newComponent<SkinFeedbackComponent>();
|
|
|
|
|
|
|
+ m_aabbLocal = modelc.getModelResource()->getBoundingVolume();
|
|
|
|
|
+ updateSpatial = true;
|
|
|
|
|
+
|
|
|
|
|
+ if(modelc.getModelResource()->getModelPatches().getSize() == countComponentsOfType<RenderComponent>())
|
|
|
|
|
+ {
|
|
|
|
|
+ // Easy, just re-init the render components
|
|
|
|
|
+ initRenderComponents();
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ // Need to create more render components, deffer it
|
|
|
|
|
+ ANKI_ASSERT(!"TODO");
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
- newComponent<MoveComponent>();
|
|
|
|
|
- newComponent<MoveFeedbackComponent>();
|
|
|
|
|
- newComponent<SpatialComponent>(this, &m_obbWorld);
|
|
|
|
|
- RenderComponent* rcomp = newComponent<RenderComponent>();
|
|
|
|
|
- rcomp->initRaster(
|
|
|
|
|
- [](RenderQueueDrawContext& ctx, ConstWeakArray<void*> userData) {
|
|
|
|
|
- const ModelNode& self = *static_cast<const ModelNode*>(userData[0]);
|
|
|
|
|
- self.draw(ctx, userData);
|
|
|
|
|
- },
|
|
|
|
|
- this, m_mergeKey);
|
|
|
|
|
- rcomp->setFlagsFromMaterial(m_model->getModelPatches()[m_modelPatchIdx].getMaterial());
|
|
|
|
|
-
|
|
|
|
|
- if(m_model->getModelPatches()[m_modelPatchIdx].getSupportedRayTracingTypes() != RayTypeBit::NONE)
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // Skin update
|
|
|
|
|
+ if(skinc.isEnabled() && skinc.getTimestamp() == globTimestamp)
|
|
|
{
|
|
{
|
|
|
- rcomp->initRayTracing(setupRayTracingInstanceQueueElement, this);
|
|
|
|
|
|
|
+ m_aabbLocal = skinc.getBoneBoundingVolumeLocalSpace();
|
|
|
|
|
+ updateSpatial = true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- m_obbLocal = m_model->getModelPatches()[m_modelPatchIdx].getBoundingShape();
|
|
|
|
|
|
|
+ // Move update
|
|
|
|
|
+ if(movec.getTimestamp() == globTimestamp)
|
|
|
|
|
+ {
|
|
|
|
|
+ getFirstComponentOfType<SpatialComponent>().setSpatialOrigin(movec.getWorldTransform().getOrigin().xyz());
|
|
|
|
|
+ updateSpatial = true;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- return Error::NONE;
|
|
|
|
|
|
|
+ // Spatial update
|
|
|
|
|
+ if(updateSpatial)
|
|
|
|
|
+ {
|
|
|
|
|
+ const Aabb aabbWorld = m_aabbLocal.getTransformed(movec.getWorldTransform());
|
|
|
|
|
+ getFirstComponentOfType<SpatialComponent>().setAabbWorldSpace(aabbWorld);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-Error ModelNode::init(const CString& modelFname)
|
|
|
|
|
|
|
+void ModelNode::initRenderComponents()
|
|
|
{
|
|
{
|
|
|
- ModelResourcePtr model;
|
|
|
|
|
- ANKI_CHECK(getResourceManager().loadResource(modelFname, model));
|
|
|
|
|
|
|
+ const ModelComponent& modelc = getFirstComponentOfType<ModelComponent>();
|
|
|
|
|
+ const ModelResourcePtr& model = modelc.getModelResource();
|
|
|
|
|
|
|
|
- // Init this
|
|
|
|
|
- ANKI_CHECK(init(model, 0));
|
|
|
|
|
|
|
+ ANKI_ASSERT(modelc.getModelResource()->getModelPatches().getSize() == countComponentsOfType<RenderComponent>());
|
|
|
|
|
+ ANKI_ASSERT(modelc.getModelResource()->getModelPatches().getSize() == m_renderProxies.getSize());
|
|
|
|
|
|
|
|
- // Create separate nodes for the model patches and make the children
|
|
|
|
|
- for(U32 i = 1; i < model->getModelPatches().getSize(); ++i)
|
|
|
|
|
|
|
+ for(U32 patchIdx = 0; patchIdx < model->getModelPatches().getSize(); ++patchIdx)
|
|
|
{
|
|
{
|
|
|
- ModelNode* other;
|
|
|
|
|
- ANKI_CHECK(getSceneGraph().newSceneNode(CString(), other, model, i));
|
|
|
|
|
|
|
+ RenderComponent& rc = getNthComponentOfType<RenderComponent>(patchIdx);
|
|
|
|
|
+ rc.initRaster(
|
|
|
|
|
+ [](RenderQueueDrawContext& ctx, ConstWeakArray<void*> userData) {
|
|
|
|
|
+ const RenderProxy& proxy = *static_cast<const RenderProxy*>(userData[0]);
|
|
|
|
|
+ const U32 modelPatchIdx = U32(&proxy - &proxy.m_node->m_renderProxies[0]);
|
|
|
|
|
+ proxy.m_node->draw(ctx, userData, modelPatchIdx);
|
|
|
|
|
+ },
|
|
|
|
|
+ &m_renderProxies[patchIdx], modelc.getRenderMergeKeys()[patchIdx]);
|
|
|
|
|
+
|
|
|
|
|
+ rc.setFlagsFromMaterial(model->getModelPatches()[patchIdx].getMaterial());
|
|
|
|
|
+
|
|
|
|
|
+ if(model->getModelPatches()[patchIdx].getSupportedRayTracingTypes() != RayTypeBit::NONE)
|
|
|
|
|
+ {
|
|
|
|
|
+ rc.initRayTracing(
|
|
|
|
|
+ [](U32 lod, const void* userData, RayTracingInstanceQueueElement& el) {
|
|
|
|
|
+ const RenderProxy& proxy = *static_cast<const RenderProxy*>(userData);
|
|
|
|
|
+ const U32 modelPatchIdx = U32(&proxy - &proxy.m_node->m_renderProxies[0]);
|
|
|
|
|
+ proxy.m_node->setupRayTracingInstanceQueueElement(lod, modelPatchIdx, el);
|
|
|
|
|
+ },
|
|
|
|
|
+ &m_renderProxies[patchIdx]);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- addChild(other);
|
|
|
|
|
|
|
+ m_renderProxies[patchIdx].m_node = this;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- return Error::NONE;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-void ModelNode::updateSpatialComponent(const MoveComponent& move)
|
|
|
|
|
-{
|
|
|
|
|
- m_obbWorld = m_obbLocal.getTransformed(move.getWorldTransform());
|
|
|
|
|
-
|
|
|
|
|
- SpatialComponent& sp = getFirstComponentOfType<SpatialComponent>();
|
|
|
|
|
- sp.markForUpdate();
|
|
|
|
|
- sp.setSpatialOrigin(move.getWorldTransform().getOrigin());
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void ModelNode::draw(RenderQueueDrawContext& ctx, ConstWeakArray<void*> userData) const
|
|
|
|
|
|
|
+void ModelNode::draw(RenderQueueDrawContext& ctx, ConstWeakArray<void*> userData, U32 modelPatchIdx) const
|
|
|
{
|
|
{
|
|
|
- ANKI_ASSERT(userData.getSize() > 0 && userData.getSize() <= MAX_INSTANCES);
|
|
|
|
|
- ANKI_ASSERT(ctx.m_key.getInstanceCount() == userData.getSize());
|
|
|
|
|
|
|
+ const U32 instanceCount = userData.getSize();
|
|
|
|
|
+ ANKI_ASSERT(instanceCount > 0 && instanceCount <= MAX_INSTANCES);
|
|
|
|
|
+ ANKI_ASSERT(ctx.m_key.getInstanceCount() == instanceCount);
|
|
|
|
|
|
|
|
CommandBufferPtr& cmdb = ctx.m_commandBuffer;
|
|
CommandBufferPtr& cmdb = ctx.m_commandBuffer;
|
|
|
|
|
|
|
|
if(ANKI_LIKELY(!ctx.m_debugDraw))
|
|
if(ANKI_LIKELY(!ctx.m_debugDraw))
|
|
|
{
|
|
{
|
|
|
- const ModelPatch& patch = m_model->getModelPatches()[m_modelPatchIdx];
|
|
|
|
|
-
|
|
|
|
|
- // That will not work on multi-draw and instanced at the same time. Make sure that there is no multi-draw
|
|
|
|
|
- // anywhere
|
|
|
|
|
- ANKI_ASSERT(patch.getSubMeshCount() == 1);
|
|
|
|
|
|
|
+ const ModelComponent& modelc = getFirstComponentOfType<ModelComponent>();
|
|
|
|
|
+ const ModelPatch& patch = modelc.getModelResource()->getModelPatches()[modelPatchIdx];
|
|
|
|
|
+ const SkinComponent& skinc = getFirstComponentOfType<SkinComponent>();
|
|
|
|
|
|
|
|
// Transforms
|
|
// Transforms
|
|
|
Array<Mat4, MAX_INSTANCES> trfs;
|
|
Array<Mat4, MAX_INSTANCES> trfs;
|
|
@@ -173,24 +176,30 @@ void ModelNode::draw(RenderQueueDrawContext& ctx, ConstWeakArray<void*> userData
|
|
|
trfs[0] = Mat4(movec.getWorldTransform());
|
|
trfs[0] = Mat4(movec.getWorldTransform());
|
|
|
prevTrfs[0] = Mat4(movec.getPreviousWorldTransform());
|
|
prevTrfs[0] = Mat4(movec.getPreviousWorldTransform());
|
|
|
Bool moved = trfs[0] != prevTrfs[0];
|
|
Bool moved = trfs[0] != prevTrfs[0];
|
|
|
- for(U32 i = 1; i < userData.getSize(); ++i)
|
|
|
|
|
|
|
+ for(U32 i = 1; i < instanceCount; ++i)
|
|
|
{
|
|
{
|
|
|
- const ModelNode& self2 = *static_cast<const ModelNode*>(userData[i]);
|
|
|
|
|
- const MoveComponent& movec = self2.getFirstComponentOfType<MoveComponent>();
|
|
|
|
|
- trfs[i] = Mat4(movec.getWorldTransform());
|
|
|
|
|
- prevTrfs[i] = Mat4(movec.getPreviousWorldTransform());
|
|
|
|
|
|
|
+ const ModelNode& otherNode = *static_cast<const RenderProxy*>(userData[i])->m_node;
|
|
|
|
|
+
|
|
|
|
|
+ const U32 otherNodeModelPatchIdx =
|
|
|
|
|
+ U32(static_cast<const RenderProxy*>(userData[i]) - &otherNode.m_renderProxies[0]);
|
|
|
|
|
+ (void)otherNodeModelPatchIdx;
|
|
|
|
|
+ ANKI_ASSERT(otherNodeModelPatchIdx == modelPatchIdx);
|
|
|
|
|
+
|
|
|
|
|
+ const MoveComponent& otherNodeMovec = otherNode.getFirstComponentOfType<MoveComponent>();
|
|
|
|
|
+ trfs[i] = Mat4(otherNodeMovec.getWorldTransform());
|
|
|
|
|
+ prevTrfs[i] = Mat4(otherNodeMovec.getPreviousWorldTransform());
|
|
|
|
|
|
|
|
moved = moved || (trfs[i] != prevTrfs[i]);
|
|
moved = moved || (trfs[i] != prevTrfs[i]);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
ctx.m_key.setVelocity(moved && ctx.m_key.getPass() == Pass::GB);
|
|
ctx.m_key.setVelocity(moved && ctx.m_key.getPass() == Pass::GB);
|
|
|
|
|
+ ctx.m_key.setSkinned(skinc.isEnabled());
|
|
|
ModelRenderingInfo modelInf;
|
|
ModelRenderingInfo modelInf;
|
|
|
- patch.getRenderingInfo(ctx.m_key, WeakArray<U8>(), modelInf);
|
|
|
|
|
|
|
+ patch.getRenderingInfo(ctx.m_key, modelInf);
|
|
|
|
|
|
|
|
// Bones storage
|
|
// Bones storage
|
|
|
- if(m_model->getSkeleton())
|
|
|
|
|
|
|
+ if(skinc.isEnabled())
|
|
|
{
|
|
{
|
|
|
- const SkinComponent& skinc = getComponentAt<SkinComponent>(0);
|
|
|
|
|
const U32 boneCount = skinc.getBoneTransforms().getSize();
|
|
const U32 boneCount = skinc.getBoneTransforms().getSize();
|
|
|
StagingGpuMemoryToken token, tokenPrev;
|
|
StagingGpuMemoryToken token, tokenPrev;
|
|
|
void* trfs = ctx.m_stagingGpuAllocator->allocateFrame(boneCount * sizeof(Mat4),
|
|
void* trfs = ctx.m_stagingGpuAllocator->allocateFrame(boneCount * sizeof(Mat4),
|
|
@@ -215,15 +224,15 @@ void ModelNode::draw(RenderQueueDrawContext& ctx, ConstWeakArray<void*> userData
|
|
|
cmdb->bindShaderProgram(modelInf.m_program);
|
|
cmdb->bindShaderProgram(modelInf.m_program);
|
|
|
|
|
|
|
|
// Uniforms
|
|
// Uniforms
|
|
|
- RenderComponent::allocateAndSetupUniforms(m_model->getModelPatches()[m_modelPatchIdx].getMaterial(), ctx,
|
|
|
|
|
- ConstWeakArray<Mat4>(&trfs[0], userData.getSize()),
|
|
|
|
|
- ConstWeakArray<Mat4>(&prevTrfs[0], userData.getSize()),
|
|
|
|
|
- *ctx.m_stagingGpuAllocator);
|
|
|
|
|
|
|
+ RenderComponent::allocateAndSetupUniforms(
|
|
|
|
|
+ modelc.getModelResource()->getModelPatches()[modelPatchIdx].getMaterial(), ctx,
|
|
|
|
|
+ ConstWeakArray<Mat4>(&trfs[0], instanceCount), ConstWeakArray<Mat4>(&prevTrfs[0], instanceCount),
|
|
|
|
|
+ *ctx.m_stagingGpuAllocator);
|
|
|
|
|
|
|
|
// Set attributes
|
|
// Set attributes
|
|
|
for(U i = 0; i < modelInf.m_vertexAttributeCount; ++i)
|
|
for(U i = 0; i < modelInf.m_vertexAttributeCount; ++i)
|
|
|
{
|
|
{
|
|
|
- const VertexAttributeInfo& attrib = modelInf.m_vertexAttributes[i];
|
|
|
|
|
|
|
+ const ModelVertexAttribute& attrib = modelInf.m_vertexAttributes[i];
|
|
|
ANKI_ASSERT(attrib.m_format != Format::NONE);
|
|
ANKI_ASSERT(attrib.m_format != Format::NONE);
|
|
|
cmdb->setVertexAttribute(U32(attrib.m_location), attrib.m_bufferBinding, attrib.m_format,
|
|
cmdb->setVertexAttribute(U32(attrib.m_location), attrib.m_bufferBinding, attrib.m_format,
|
|
|
attrib.m_relativeOffset);
|
|
attrib.m_relativeOffset);
|
|
@@ -232,29 +241,27 @@ void ModelNode::draw(RenderQueueDrawContext& ctx, ConstWeakArray<void*> userData
|
|
|
// Set vertex buffers
|
|
// Set vertex buffers
|
|
|
for(U32 i = 0; i < modelInf.m_vertexBufferBindingCount; ++i)
|
|
for(U32 i = 0; i < modelInf.m_vertexBufferBindingCount; ++i)
|
|
|
{
|
|
{
|
|
|
- const VertexBufferBinding& binding = modelInf.m_vertexBufferBindings[i];
|
|
|
|
|
|
|
+ const ModelVertexBufferBinding& binding = modelInf.m_vertexBufferBindings[i];
|
|
|
cmdb->bindVertexBuffer(i, binding.m_buffer, binding.m_offset, binding.m_stride, VertexStepRate::VERTEX);
|
|
cmdb->bindVertexBuffer(i, binding.m_buffer, binding.m_offset, binding.m_stride, VertexStepRate::VERTEX);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Index buffer
|
|
// Index buffer
|
|
|
- cmdb->bindIndexBuffer(modelInf.m_indexBuffer, 0, IndexType::U16);
|
|
|
|
|
|
|
+ cmdb->bindIndexBuffer(modelInf.m_indexBuffer, modelInf.m_indexBufferOffset, IndexType::U16);
|
|
|
|
|
|
|
|
// Draw
|
|
// Draw
|
|
|
- cmdb->drawElements(PrimitiveTopology::TRIANGLES, modelInf.m_indicesCountArray[0], userData.getSize(),
|
|
|
|
|
- U32(modelInf.m_indicesOffsetArray[0] / sizeof(U16)), 0, 0);
|
|
|
|
|
|
|
+ cmdb->drawElements(PrimitiveTopology::TRIANGLES, modelInf.m_indexCount, instanceCount, 0, 0, 0);
|
|
|
}
|
|
}
|
|
|
else
|
|
else
|
|
|
{
|
|
{
|
|
|
// Draw the bounding volumes
|
|
// Draw the bounding volumes
|
|
|
|
|
|
|
|
- Mat4* const mvps = ctx.m_frameAllocator.newArray<Mat4>(userData.getSize());
|
|
|
|
|
- for(U32 i = 0; i < userData.getSize(); ++i)
|
|
|
|
|
|
|
+ Mat4* const mvps = ctx.m_frameAllocator.newArray<Mat4>(instanceCount);
|
|
|
|
|
+ for(U32 i = 0; i < instanceCount; ++i)
|
|
|
{
|
|
{
|
|
|
- const ModelNode& self2 = *static_cast<const ModelNode*>(userData[i]);
|
|
|
|
|
-
|
|
|
|
|
- const Mat3 rot = self2.m_obbWorld.getRotation().getRotationPart();
|
|
|
|
|
- const Vec4 tsl = self2.m_obbWorld.getCenter().xyz1();
|
|
|
|
|
- const Vec3 scale = self2.m_obbWorld.getExtend().xyz();
|
|
|
|
|
|
|
+ const ModelNode& otherNode = *static_cast<const RenderProxy*>(userData[i])->m_node;
|
|
|
|
|
+ const Aabb& box = otherNode.getFirstComponentOfType<SpatialComponent>().getAabbWorldSpace();
|
|
|
|
|
+ const Vec4 tsl = (box.getMin() + box.getMax()) / 2.0f;
|
|
|
|
|
+ const Vec3 scale = (box.getMax().xyz() - box.getMin().xyz()) / 2.0f;
|
|
|
|
|
|
|
|
// Set non uniform scale. Add a margin to avoid flickering
|
|
// Set non uniform scale. Add a margin to avoid flickering
|
|
|
Mat3 nonUniScale = Mat3::getZero();
|
|
Mat3 nonUniScale = Mat3::getZero();
|
|
@@ -263,7 +270,7 @@ void ModelNode::draw(RenderQueueDrawContext& ctx, ConstWeakArray<void*> userData
|
|
|
nonUniScale(1, 1) = scale.y() * MARGIN;
|
|
nonUniScale(1, 1) = scale.y() * MARGIN;
|
|
|
nonUniScale(2, 2) = scale.z() * MARGIN;
|
|
nonUniScale(2, 2) = scale.z() * MARGIN;
|
|
|
|
|
|
|
|
- mvps[i] = ctx.m_viewProjectionMatrix * Mat4(tsl, rot * nonUniScale, 1.0f);
|
|
|
|
|
|
|
+ mvps[i] = ctx.m_viewProjectionMatrix * Mat4(tsl.xyz1(), Mat3::getIdentity() * nonUniScale, 1.0f);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const Bool enableDepthTest = ctx.m_debugDrawFlags.get(RenderQueueDebugDrawFlag::DEPTH_TEST_ON);
|
|
const Bool enableDepthTest = ctx.m_debugDrawFlags.get(RenderQueueDebugDrawFlag::DEPTH_TEST_ON);
|
|
@@ -276,14 +283,16 @@ void ModelNode::draw(RenderQueueDrawContext& ctx, ConstWeakArray<void*> userData
|
|
|
cmdb->setDepthCompareOperation(CompareOperation::ALWAYS);
|
|
cmdb->setDepthCompareOperation(CompareOperation::ALWAYS);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- m_dbgDrawer.drawCubes(ConstWeakArray<Mat4>(mvps, userData.getSize()), Vec4(1.0f, 0.0f, 1.0f, 1.0f), 2.0f,
|
|
|
|
|
- ctx.m_debugDrawFlags.get(RenderQueueDebugDrawFlag::DITHERED_DEPTH_TEST_ON), 2.0f,
|
|
|
|
|
- *ctx.m_stagingGpuAllocator, cmdb);
|
|
|
|
|
|
|
+ getSceneGraph().getDebugDrawer().drawCubes(
|
|
|
|
|
+ ConstWeakArray<Mat4>(mvps, instanceCount), Vec4(1.0f, 0.0f, 1.0f, 1.0f), 2.0f,
|
|
|
|
|
+ ctx.m_debugDrawFlags.get(RenderQueueDebugDrawFlag::DITHERED_DEPTH_TEST_ON), 2.0f,
|
|
|
|
|
+ *ctx.m_stagingGpuAllocator, cmdb);
|
|
|
|
|
|
|
|
- ctx.m_frameAllocator.deleteArray(mvps, userData.getSize());
|
|
|
|
|
|
|
+ ctx.m_frameAllocator.deleteArray(mvps, instanceCount);
|
|
|
|
|
|
|
|
// Bones
|
|
// Bones
|
|
|
- if(m_model->getSkeleton())
|
|
|
|
|
|
|
+ const SkinComponent& skinc = getFirstComponentOfType<SkinComponent>();
|
|
|
|
|
+ if(skinc.isEnabled())
|
|
|
{
|
|
{
|
|
|
const SkinComponent& skinc = getComponentAt<SkinComponent>(0);
|
|
const SkinComponent& skinc = getComponentAt<SkinComponent>(0);
|
|
|
SkeletonResourcePtr skeleton = skinc.getSkeleronResource();
|
|
SkeletonResourcePtr skeleton = skinc.getSkeleronResource();
|
|
@@ -321,13 +330,15 @@ void ModelNode::draw(RenderQueueDrawContext& ctx, ConstWeakArray<void*> userData
|
|
|
|
|
|
|
|
const Mat4 mvp =
|
|
const Mat4 mvp =
|
|
|
ctx.m_viewProjectionMatrix * Mat4(getFirstComponentOfType<MoveComponent>().getWorldTransform());
|
|
ctx.m_viewProjectionMatrix * Mat4(getFirstComponentOfType<MoveComponent>().getWorldTransform());
|
|
|
- m_dbgDrawer.drawLines(ConstWeakArray<Mat4>(&mvp, 1), Vec4(1.0f), 20.0f,
|
|
|
|
|
- ctx.m_debugDrawFlags.get(RenderQueueDebugDrawFlag::DITHERED_DEPTH_TEST_ON), lines,
|
|
|
|
|
- *ctx.m_stagingGpuAllocator, cmdb);
|
|
|
|
|
-
|
|
|
|
|
- m_dbgDrawer.drawLines(ConstWeakArray<Mat4>(&mvp, 1), Vec4(0.7f, 0.7f, 0.7f, 1.0f), 5.0f,
|
|
|
|
|
- ctx.m_debugDrawFlags.get(RenderQueueDebugDrawFlag::DITHERED_DEPTH_TEST_ON),
|
|
|
|
|
- chidlessLines, *ctx.m_stagingGpuAllocator, cmdb);
|
|
|
|
|
|
|
+ getSceneGraph().getDebugDrawer().drawLines(
|
|
|
|
|
+ ConstWeakArray<Mat4>(&mvp, 1), Vec4(1.0f), 20.0f,
|
|
|
|
|
+ ctx.m_debugDrawFlags.get(RenderQueueDebugDrawFlag::DITHERED_DEPTH_TEST_ON), lines,
|
|
|
|
|
+ *ctx.m_stagingGpuAllocator, cmdb);
|
|
|
|
|
+
|
|
|
|
|
+ getSceneGraph().getDebugDrawer().drawLines(
|
|
|
|
|
+ ConstWeakArray<Mat4>(&mvp, 1), Vec4(0.7f, 0.7f, 0.7f, 1.0f), 5.0f,
|
|
|
|
|
+ ctx.m_debugDrawFlags.get(RenderQueueDebugDrawFlag::DITHERED_DEPTH_TEST_ON), chidlessLines,
|
|
|
|
|
+ *ctx.m_stagingGpuAllocator, cmdb);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Restore state
|
|
// Restore state
|
|
@@ -338,12 +349,11 @@ void ModelNode::draw(RenderQueueDrawContext& ctx, ConstWeakArray<void*> userData
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void ModelNode::setupRayTracingInstanceQueueElement(U32 lod, const void* userData, RayTracingInstanceQueueElement& el)
|
|
|
|
|
|
|
+void ModelNode::setupRayTracingInstanceQueueElement(U32 lod, U32 modelPatchIdx,
|
|
|
|
|
+ RayTracingInstanceQueueElement& el) const
|
|
|
{
|
|
{
|
|
|
- const ModelNode& self = *static_cast<const ModelNode*>(userData);
|
|
|
|
|
- const ModelPatch& patch = self.m_model->getModelPatches()[self.m_modelPatchIdx];
|
|
|
|
|
-
|
|
|
|
|
- // printf("%s\n", patch.getMaterial()->getFilename().cstr());
|
|
|
|
|
|
|
+ const ModelComponent& modelc = getFirstComponentOfType<ModelComponent>();
|
|
|
|
|
+ const ModelPatch& patch = modelc.getModelResource()->getModelPatches()[modelPatchIdx];
|
|
|
|
|
|
|
|
ModelRayTracingInfo info;
|
|
ModelRayTracingInfo info;
|
|
|
patch.getRayTracingInfo(lod, info);
|
|
patch.getRayTracingInfo(lod, info);
|
|
@@ -355,7 +365,7 @@ void ModelNode::setupRayTracingInstanceQueueElement(U32 lod, const void* userDat
|
|
|
|
|
|
|
|
// Set the descriptor
|
|
// Set the descriptor
|
|
|
el.m_modelDescriptor = info.m_descriptor;
|
|
el.m_modelDescriptor = info.m_descriptor;
|
|
|
- const MoveComponent& movec = self.getFirstComponentOfType<MoveComponent>();
|
|
|
|
|
|
|
+ const MoveComponent& movec = getFirstComponentOfType<MoveComponent>();
|
|
|
const Mat3x4 worldTrf(movec.getWorldTransform());
|
|
const Mat3x4 worldTrf(movec.getWorldTransform());
|
|
|
memcpy(&el.m_modelDescriptor.m_worldTransform, &worldTrf, sizeof(worldTrf));
|
|
memcpy(&el.m_modelDescriptor.m_worldTransform, &worldTrf, sizeof(worldTrf));
|
|
|
el.m_modelDescriptor.m_worldRotation = movec.getWorldTransform().getRotation().getRotationPart();
|
|
el.m_modelDescriptor.m_worldRotation = movec.getWorldTransform().getRotation().getRotationPart();
|