|
@@ -24,7 +24,8 @@ ModelPatchNode::ModelPatchNode(
|
|
|
: SceneNode(name, scene),
|
|
: SceneNode(name, scene),
|
|
|
RenderComponent(this),
|
|
RenderComponent(this),
|
|
|
SpatialComponent(this),
|
|
SpatialComponent(this),
|
|
|
- m_modelPatch(modelPatch)
|
|
|
|
|
|
|
+ m_modelPatch(modelPatch),
|
|
|
|
|
+ m_spatials(getSceneAllocator())
|
|
|
{
|
|
{
|
|
|
addComponent(static_cast<RenderComponent*>(this));
|
|
addComponent(static_cast<RenderComponent*>(this));
|
|
|
addComponent(static_cast<SpatialComponent*>(this));
|
|
addComponent(static_cast<SpatialComponent*>(this));
|
|
@@ -100,109 +101,53 @@ void ModelPatchNode::getRenderWorldTransform(U index, Transform& trf)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//==============================================================================
|
|
//==============================================================================
|
|
|
-void ModelPatchNode::frameUpdate(F32, F32, SceneNode::UpdateType uptype)
|
|
|
|
|
|
|
+void ModelPatchNode::updateInstanceSpatials(
|
|
|
|
|
+ const SceneFrameVector<MoveComponent*>& instanceMoves)
|
|
|
{
|
|
{
|
|
|
- if(uptype != SceneNode::ASYNC_UPDATE)
|
|
|
|
|
- {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ Bool fullUpdate = false;
|
|
|
|
|
|
|
|
- SceneNode* parent = &getParent()->downCast<SceneNode>();
|
|
|
|
|
- ANKI_ASSERT(parent);
|
|
|
|
|
-
|
|
|
|
|
- // Update first OBB
|
|
|
|
|
- const MoveComponent& parentMove = parent->getComponent<MoveComponent>();
|
|
|
|
|
- if(parentMove.getTimestamp() == getGlobTimestamp())
|
|
|
|
|
|
|
+ if(m_spatials.size() < instanceMoves.size())
|
|
|
{
|
|
{
|
|
|
- m_obb = m_modelPatch->getBoundingShape().getTransformed(
|
|
|
|
|
- parentMove.getWorldTransform());
|
|
|
|
|
|
|
+ // We need to add spatials
|
|
|
|
|
+
|
|
|
|
|
+ fullUpdate = true;
|
|
|
|
|
|
|
|
- SpatialComponent::markForUpdate();
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ U diff = instanceMoves.size() - m_spatials.size();
|
|
|
|
|
|
|
|
- // Get the move components of the instances of the parent
|
|
|
|
|
- SceneFrameVector<MoveComponent*> instanceMoves(getSceneFrameAllocator());
|
|
|
|
|
- Timestamp instancesTimestamp = 0;
|
|
|
|
|
- parent->visitThisAndChildren<SceneNode>([&](SceneNode& sn)
|
|
|
|
|
- {
|
|
|
|
|
- if(sn.tryGetComponent<InstanceComponent>())
|
|
|
|
|
|
|
+ while(diff-- != 0)
|
|
|
{
|
|
{
|
|
|
- MoveComponent& move = sn.getComponent<MoveComponent>();
|
|
|
|
|
|
|
+ ObbSpatialComponent* newSpatial = getSceneAllocator().
|
|
|
|
|
+ newInstance<ObbSpatialComponent>(this);
|
|
|
|
|
|
|
|
- instanceMoves.push_back(&move);
|
|
|
|
|
|
|
+ addComponent(newSpatial);
|
|
|
|
|
|
|
|
- instancesTimestamp =
|
|
|
|
|
- std::max(instancesTimestamp, move.getTimestamp());
|
|
|
|
|
|
|
+ m_spatials.push_back(newSpatial);
|
|
|
}
|
|
}
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- // Instancing?
|
|
|
|
|
- if(instanceMoves.size() != 0)
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+ else if(m_spatials.size() > instanceMoves.size())
|
|
|
{
|
|
{
|
|
|
- Bool needsUpdate = false;
|
|
|
|
|
|
|
+ // Need to remove spatials
|
|
|
|
|
|
|
|
- // Get the spatials and their update time
|
|
|
|
|
- SceneFrameVector<ObbSpatialComponent*>
|
|
|
|
|
- spatials(getSceneFrameAllocator());
|
|
|
|
|
|
|
+ fullUpdate = true;
|
|
|
|
|
|
|
|
- Timestamp spatialsTimestamp = 0;
|
|
|
|
|
- U count = 0;
|
|
|
|
|
-
|
|
|
|
|
- iterateComponentsOfType<SpatialComponent>([&](SpatialComponent& sp)
|
|
|
|
|
- {
|
|
|
|
|
- // Skip the first
|
|
|
|
|
- if(count != 0)
|
|
|
|
|
- {
|
|
|
|
|
- ObbSpatialComponent* msp =
|
|
|
|
|
- staticCastPtr<ObbSpatialComponent*>(&sp);
|
|
|
|
|
-
|
|
|
|
|
- spatialsTimestamp =
|
|
|
|
|
- std::max(spatialsTimestamp, msp->getTimestamp());
|
|
|
|
|
-
|
|
|
|
|
- spatials.push_back(msp);
|
|
|
|
|
- }
|
|
|
|
|
- ++count;
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- // If we need to add spatials
|
|
|
|
|
- if(spatials.size() < instanceMoves.size())
|
|
|
|
|
- {
|
|
|
|
|
- needsUpdate = true;
|
|
|
|
|
- U diff = instanceMoves.size() - spatials.size();
|
|
|
|
|
-
|
|
|
|
|
- while(diff-- != 0)
|
|
|
|
|
- {
|
|
|
|
|
- ObbSpatialComponent* newSpatial = getSceneAllocator().
|
|
|
|
|
- newInstance<ObbSpatialComponent>(this);
|
|
|
|
|
-
|
|
|
|
|
- addComponent(newSpatial);
|
|
|
|
|
|
|
+ // TODO
|
|
|
|
|
+ ANKI_ASSERT(0 && "TODO");
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- spatials.push_back(newSpatial);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- // If we need to remove spatials
|
|
|
|
|
- else if(spatials.size() > instanceMoves.size())
|
|
|
|
|
- {
|
|
|
|
|
- needsUpdate = true;
|
|
|
|
|
|
|
+ U count = instanceMoves.size();
|
|
|
|
|
+ while(count-- != 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ ObbSpatialComponent& sp = *m_spatials[count];
|
|
|
|
|
+ const MoveComponent& inst = *instanceMoves[count];
|
|
|
|
|
|
|
|
- // TODO
|
|
|
|
|
- ANKI_ASSERT(0 && "TODO");
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Now update all spatials if needed
|
|
|
|
|
- if(needsUpdate || spatialsTimestamp < instancesTimestamp)
|
|
|
|
|
|
|
+ if(sp.getTimestamp() < inst.getTimestamp() || fullUpdate)
|
|
|
{
|
|
{
|
|
|
- for(U i = 0; i < spatials.size(); i++)
|
|
|
|
|
- {
|
|
|
|
|
- ObbSpatialComponent* sp = spatials[i];
|
|
|
|
|
-
|
|
|
|
|
- sp->obb = m_modelPatch->getBoundingShape().getTransformed(
|
|
|
|
|
- instanceMoves[i]->getWorldTransform());
|
|
|
|
|
|
|
+ sp.m_obb = m_modelPatch->getBoundingShape().getTransformed(
|
|
|
|
|
+ inst.getWorldTransform());
|
|
|
|
|
|
|
|
- sp->markForUpdate();
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ sp.markForUpdate();
|
|
|
}
|
|
}
|
|
|
- } // end instancing
|
|
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//==============================================================================
|
|
//==============================================================================
|
|
@@ -215,18 +160,22 @@ ModelNode::ModelNode(
|
|
|
const CString& modelFname)
|
|
const CString& modelFname)
|
|
|
: SceneNode(name, scene),
|
|
: SceneNode(name, scene),
|
|
|
MoveComponent(this),
|
|
MoveComponent(this),
|
|
|
|
|
+ m_modelPatches(getSceneAllocator()),
|
|
|
m_transforms(getSceneAllocator()),
|
|
m_transforms(getSceneAllocator()),
|
|
|
m_transformsTimestamp(0)
|
|
m_transformsTimestamp(0)
|
|
|
{
|
|
{
|
|
|
addComponent(static_cast<MoveComponent*>(this));
|
|
addComponent(static_cast<MoveComponent*>(this));
|
|
|
|
|
|
|
|
m_model.load(modelFname, &getResourceManager());
|
|
m_model.load(modelFname, &getResourceManager());
|
|
|
|
|
+ m_modelPatches.reserve(m_model->getModelPatches().size());
|
|
|
|
|
|
|
|
for(const ModelPatchBase* patch : m_model->getModelPatches())
|
|
for(const ModelPatchBase* patch : m_model->getModelPatches())
|
|
|
{
|
|
{
|
|
|
ModelPatchNode* mpn =
|
|
ModelPatchNode* mpn =
|
|
|
getSceneGraph().newSceneNode<ModelPatchNode>(CString(), patch);
|
|
getSceneGraph().newSceneNode<ModelPatchNode>(CString(), patch);
|
|
|
|
|
|
|
|
|
|
+ m_modelPatches.push_back(mpn);
|
|
|
|
|
+
|
|
|
SceneObject::addChild(mpn);
|
|
SceneObject::addChild(mpn);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -262,41 +211,40 @@ ModelNode::~ModelNode()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//==============================================================================
|
|
//==============================================================================
|
|
|
-void ModelNode::frameUpdate(F32, F32, SceneNode::UpdateType uptype)
|
|
|
|
|
|
|
+void ModelNode::frameUpdate(F32, F32)
|
|
|
{
|
|
{
|
|
|
- if(uptype != SceneNode::ASYNC_UPDATE)
|
|
|
|
|
- {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Get the move components of the instances of the parent
|
|
|
|
|
|
|
+ // Gather the move components of the instances
|
|
|
SceneFrameVector<MoveComponent*> instanceMoves(getSceneFrameAllocator());
|
|
SceneFrameVector<MoveComponent*> instanceMoves(getSceneFrameAllocator());
|
|
|
Timestamp instancesTimestamp = 0;
|
|
Timestamp instancesTimestamp = 0;
|
|
|
- SceneObject::visitThisAndChildren<SceneNode>([&](SceneNode& sn)
|
|
|
|
|
- {
|
|
|
|
|
- if(sn.tryGetComponent<InstanceComponent>())
|
|
|
|
|
|
|
+ SceneObject::visitChildren([&](SceneObject& obj)
|
|
|
|
|
+ {
|
|
|
|
|
+ if(obj.getType() == SceneNode::getClassType())
|
|
|
{
|
|
{
|
|
|
- MoveComponent& move = sn.getComponent<MoveComponent>();
|
|
|
|
|
|
|
+ SceneNode& sn = obj.downCast<SceneNode>();
|
|
|
|
|
+ if(sn.tryGetComponent<InstanceComponent>())
|
|
|
|
|
+ {
|
|
|
|
|
+ MoveComponent& move = sn.getComponent<MoveComponent>();
|
|
|
|
|
|
|
|
- instanceMoves.push_back(&move);
|
|
|
|
|
|
|
+ instanceMoves.push_back(&move);
|
|
|
|
|
|
|
|
- instancesTimestamp =
|
|
|
|
|
- std::max(instancesTimestamp, move.getTimestamp());
|
|
|
|
|
|
|
+ instancesTimestamp =
|
|
|
|
|
+ std::max(instancesTimestamp, move.getTimestamp());
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
- // If instancing
|
|
|
|
|
|
|
+ // If having instances
|
|
|
if(instanceMoves.size() != 0)
|
|
if(instanceMoves.size() != 0)
|
|
|
{
|
|
{
|
|
|
- Bool transformsNeedUpdate = false;
|
|
|
|
|
|
|
+ Bool fullUpdate = false;
|
|
|
|
|
|
|
|
if(instanceMoves.size() != m_transforms.size())
|
|
if(instanceMoves.size() != m_transforms.size())
|
|
|
{
|
|
{
|
|
|
- transformsNeedUpdate = true;
|
|
|
|
|
|
|
+ fullUpdate = true;
|
|
|
m_transforms.resize(instanceMoves.size());
|
|
m_transforms.resize(instanceMoves.size());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if(transformsNeedUpdate || m_transformsTimestamp < instancesTimestamp)
|
|
|
|
|
|
|
+ if(fullUpdate || m_transformsTimestamp < instancesTimestamp)
|
|
|
{
|
|
{
|
|
|
m_transformsTimestamp = instancesTimestamp;
|
|
m_transformsTimestamp = instancesTimestamp;
|
|
|
|
|
|
|
@@ -305,6 +253,25 @@ void ModelNode::frameUpdate(F32, F32, SceneNode::UpdateType uptype)
|
|
|
m_transforms[i] = instanceMoves[i]->getWorldTransform();
|
|
m_transforms[i] = instanceMoves[i]->getWorldTransform();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ // Update children
|
|
|
|
|
+ for(ModelPatchNode* child : m_modelPatches)
|
|
|
|
|
+ {
|
|
|
|
|
+ child->updateInstanceSpatials(instanceMoves);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+//==============================================================================
|
|
|
|
|
+void ModelNode::onMoveComponentUpdate(SceneNode&, F32, F32)
|
|
|
|
|
+{
|
|
|
|
|
+ // Inform the children about the moves
|
|
|
|
|
+ for(ModelPatchNode* child : m_modelPatches)
|
|
|
|
|
+ {
|
|
|
|
|
+ child->m_obb = child->m_modelPatch->getBoundingShape().getTransformed(
|
|
|
|
|
+ getWorldTransform());
|
|
|
|
|
+
|
|
|
|
|
+ child->SpatialComponent::markForUpdate();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|