|
|
@@ -1,25 +1,14 @@
|
|
|
#include "anki/scene/ModelNode.h"
|
|
|
#include "anki/scene/SceneGraph.h"
|
|
|
+#include "anki/scene/InstanceNode.h"
|
|
|
#include "anki/resource/Model.h"
|
|
|
#include "anki/resource/Skeleton.h"
|
|
|
#include "anki/physics/RigidBody.h"
|
|
|
#include "anki/physics/PhysicsWorld.h"
|
|
|
+#include "anki/gl/Drawcall.h"
|
|
|
|
|
|
namespace anki {
|
|
|
|
|
|
-//==============================================================================
|
|
|
-// Instance =
|
|
|
-//==============================================================================
|
|
|
-
|
|
|
-//==============================================================================
|
|
|
-Instance::Instance(
|
|
|
- const char* name, SceneGraph* scene)
|
|
|
- : SceneNode(name, scene),
|
|
|
- MoveComponent(this)
|
|
|
-{
|
|
|
- addComponent(static_cast<MoveComponent*>(this));
|
|
|
-}
|
|
|
-
|
|
|
//==============================================================================
|
|
|
// ModelPatchNode =
|
|
|
//==============================================================================
|
|
|
@@ -27,129 +16,105 @@ Instance::Instance(
|
|
|
//==============================================================================
|
|
|
ModelPatchNode::ModelPatchNode(
|
|
|
const char* name, SceneGraph* scene,
|
|
|
- const ModelPatchBase* modelPatch_, U instancesCount)
|
|
|
+ const ModelPatchBase* modelPatch_)
|
|
|
: SceneNode(name, scene),
|
|
|
- MoveComponent(this, MoveComponent::MF_IGNORE_LOCAL_TRANSFORM),
|
|
|
RenderComponent(this),
|
|
|
- SpatialComponent(this, &obb),
|
|
|
- modelPatch(modelPatch_),
|
|
|
- instances(getSceneAllocator()),
|
|
|
- transforms(getSceneAllocator())
|
|
|
+ SpatialComponent(this),
|
|
|
+ modelPatch(modelPatch_)
|
|
|
{
|
|
|
- sceneNodeProtected.moveC = this;
|
|
|
- sceneNodeProtected.renderC = this;
|
|
|
- sceneNodeProtected.spatialC = this;
|
|
|
+ addComponent(static_cast<RenderComponent*>(this));
|
|
|
+ addComponent(static_cast<SpatialComponent*>(this));
|
|
|
|
|
|
RenderComponent::init();
|
|
|
-
|
|
|
- // Create the instances as ModelPatchNodeInstance
|
|
|
- if(instancesCount > 1)
|
|
|
- {
|
|
|
- instances.resize(instancesCount, nullptr);
|
|
|
- transforms.resize(instancesCount, Transform::getIdentity());
|
|
|
-
|
|
|
- Vec3 pos = Vec3(0.0);
|
|
|
-
|
|
|
- for(U i = 0; i < instancesCount; i++)
|
|
|
- {
|
|
|
- ModelPatchNodeInstance* instance;
|
|
|
- getSceneGraph().newSceneNode(instance, nullptr, this);
|
|
|
-
|
|
|
- //MoveComponent::addChild(instance);
|
|
|
-
|
|
|
- instance->setLocalOrigin(pos);
|
|
|
- pos.x() += 2.0;
|
|
|
-
|
|
|
- SpatialComponent::addChild(instance);
|
|
|
- instances[i] = instance;
|
|
|
- }
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
//==============================================================================
|
|
|
ModelPatchNode::~ModelPatchNode()
|
|
|
-{
|
|
|
- for(ModelPatchNodeInstance* instance : instances)
|
|
|
- {
|
|
|
- getSceneGraph().deleteSceneNode(instance);
|
|
|
- }
|
|
|
-}
|
|
|
+{}
|
|
|
|
|
|
//==============================================================================
|
|
|
void ModelPatchNode::getRenderingData(
|
|
|
const PassLodKey& key,
|
|
|
- const Vao*& vao, const ShaderProgram*& prog,
|
|
|
const U32* subMeshIndicesArray, U subMeshIndicesCount,
|
|
|
- Drawcall& dracall)
|
|
|
+ const Vao*& vao, const ShaderProgram*& prog,
|
|
|
+ Drawcall& dc)
|
|
|
{
|
|
|
- drawcall.prim
|
|
|
+ dc.primitiveType = GL_TRIANGLES;
|
|
|
+ dc.indicesType = GL_UNSIGNED_SHORT;
|
|
|
+
|
|
|
+ U spatialsCount = 0;
|
|
|
+ iterateComponentsOfType<SpatialComponent>([&](SpatialComponent&)
|
|
|
+ {
|
|
|
+ ++spatialsCount;
|
|
|
+ });
|
|
|
+
|
|
|
+ dc.instancesCount = spatialsCount;
|
|
|
|
|
|
modelPatch->getRenderingDataSub(key, vao, prog,
|
|
|
subMeshIndicesArray, subMeshIndicesCount,
|
|
|
- indicesCountArray, indicesOffsetArray, drawcallCount);
|
|
|
+ dc.countArray, dc.offsetArray, dc.drawCount);
|
|
|
}
|
|
|
|
|
|
//==============================================================================
|
|
|
const Transform* ModelPatchNode::getRenderWorldTransforms()
|
|
|
{
|
|
|
- if(transforms.size() == 0)
|
|
|
+ SceneNode* parent = staticCast<SceneNode*>(getParent());
|
|
|
+ ANKI_ASSERT(parent);
|
|
|
+ MoveComponent& move = parent->getComponent<MoveComponent>();
|
|
|
+
|
|
|
+ if(1) // XXX
|
|
|
{
|
|
|
// NO instancing
|
|
|
- return &getWorldTransform();
|
|
|
+ return &move.getWorldTransform();
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
// Instancing
|
|
|
|
|
|
- ANKI_ASSERT(transforms.size() == instances.size());
|
|
|
-
|
|
|
- // Set the transforms buffer
|
|
|
- for(U i = 0; i < instances.size(); i++)
|
|
|
- {
|
|
|
- transforms[i] = instances[i]->getWorldTransform();
|
|
|
- }
|
|
|
-
|
|
|
- return &transforms[0];
|
|
|
+ // XXX
|
|
|
+ ANKI_ASSERT(0 && "todo");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//==============================================================================
|
|
|
-void ModelPatchNode::moveUpdate()
|
|
|
+void ModelPatchNode::frameUpdate(F32, F32, SceneNode::UpdateType uptype)
|
|
|
{
|
|
|
- if(instances.size() == 0)
|
|
|
+ if(uptype != SceneNode::ASYNC_UPDATE)
|
|
|
{
|
|
|
- // NO instancing
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
- obb = modelPatch->getBoundingShape().getTransformed(
|
|
|
- getWorldTransform());
|
|
|
+ SceneNode* parent = staticCast<SceneNode*>(getParent());
|
|
|
+ ANKI_ASSERT(parent);
|
|
|
|
|
|
- SpatialComponent::markForUpdate();
|
|
|
- }
|
|
|
- else
|
|
|
+ // Count the instances of the parent
|
|
|
+ U instancesCount = 0;
|
|
|
+ parent->visitThisAndChildren([&](SceneObject& so)
|
|
|
{
|
|
|
- // Instancing
|
|
|
+ SceneNode* sn = staticCast<SceneNode*>(&so);
|
|
|
|
|
|
- // Do nothing. You cannot update the obb because the instances have
|
|
|
- // not been updated their CSs yet. The update will be triggered by the
|
|
|
- // last instance.
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-//==============================================================================
|
|
|
-void ModelPatchNode::updateSpatialCs()
|
|
|
-{
|
|
|
- ANKI_ASSERT(instances.size() > 0);
|
|
|
-
|
|
|
- obb = instances[0]->obb;
|
|
|
+ if(sn->tryGetComponent<InstanceComponent>())
|
|
|
+ {
|
|
|
+ ++instancesCount;
|
|
|
+ }
|
|
|
+ });
|
|
|
|
|
|
- for(U i = 1; i < instances.size(); i++)
|
|
|
+ if(instancesCount == 0)
|
|
|
{
|
|
|
- ANKI_ASSERT(instances[i]);
|
|
|
+ // No instances
|
|
|
+ const MoveComponent& parentMove = parent->getComponent<MoveComponent>();
|
|
|
|
|
|
- obb = obb.getCompoundShape(instances[i]->obb);
|
|
|
+ if(parentMove.getTimestamp() == getGlobTimestamp())
|
|
|
+ {
|
|
|
+ obb = modelPatch->getBoundingShape().getTransformed(
|
|
|
+ parentMove.getWorldTransform());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // XXX
|
|
|
+ ANKI_ASSERT(0 && "todo");
|
|
|
}
|
|
|
-
|
|
|
- SpatialComponent::markForUpdate();
|
|
|
}
|
|
|
|
|
|
//==============================================================================
|
|
|
@@ -159,27 +124,21 @@ void ModelPatchNode::updateSpatialCs()
|
|
|
//==============================================================================
|
|
|
ModelNode::ModelNode(
|
|
|
const char* name, SceneGraph* scene,
|
|
|
- const char* modelFname, U instances)
|
|
|
+ const char* modelFname)
|
|
|
: SceneNode(name, scene),
|
|
|
MoveComponent(this),
|
|
|
- patches(getSceneAllocator())
|
|
|
+ transforms(getSceneAllocator())
|
|
|
{
|
|
|
- sceneNodeProtected.moveC = this;
|
|
|
+ addComponent(static_cast<MoveComponent*>(this));
|
|
|
|
|
|
model.load(modelFname);
|
|
|
|
|
|
- patches.reserve(model->getModelPatches().size());
|
|
|
-
|
|
|
- U i = 0;
|
|
|
for(const ModelPatchBase* patch : model->getModelPatches())
|
|
|
{
|
|
|
ModelPatchNode* mpn;
|
|
|
- getSceneGraph().newSceneNode(mpn, nullptr, patch, instances);
|
|
|
+ getSceneGraph().newSceneNode(mpn, nullptr, patch);
|
|
|
|
|
|
- MoveComponent::addChild(mpn);
|
|
|
-
|
|
|
- patches.push_back(mpn);
|
|
|
- ++i;
|
|
|
+ SceneObject::addChild(mpn);
|
|
|
}
|
|
|
|
|
|
// Load rigid body
|
|
|
@@ -188,51 +147,24 @@ ModelNode::ModelNode(
|
|
|
RigidBody::Initializer init;
|
|
|
init.mass = 1.0;
|
|
|
init.shape = const_cast<btCollisionShape*>(model->getCollisionShape());
|
|
|
- init.startTrf.getOrigin().y() = 20.0;
|
|
|
+ init.node = this;
|
|
|
|
|
|
RigidBody* body;
|
|
|
|
|
|
getSceneGraph().getPhysics().newPhysicsObject<RigidBody>(
|
|
|
body, init);
|
|
|
|
|
|
- sceneNodeProtected.rigidBodyC = body;
|
|
|
+ addComponent(static_cast<RigidBody*>(body));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//==============================================================================
|
|
|
ModelNode::~ModelNode()
|
|
|
{
|
|
|
- for(ModelPatchNode* patch : patches)
|
|
|
- {
|
|
|
- getSceneGraph().deleteSceneNode(patch);
|
|
|
- }
|
|
|
-
|
|
|
- if(sceneNodeProtected.rigidBodyC)
|
|
|
- {
|
|
|
- getSceneGraph().getPhysics().deletePhysicsObject(
|
|
|
- sceneNodeProtected.rigidBodyC);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-//==============================================================================
|
|
|
-void ModelNode::setInstanceLocalTransform(U instanceIndex, const Transform& trf)
|
|
|
-{
|
|
|
- ANKI_ASSERT(patches.size() > 0);
|
|
|
-
|
|
|
- if(patches[0]->instances.size() > 0)
|
|
|
+ RigidBody* body = tryGetComponent<RigidBody>();
|
|
|
+ if(body)
|
|
|
{
|
|
|
- ANKI_ASSERT(instanceIndex < patches[0]->instances.size());
|
|
|
-
|
|
|
- for(ModelPatchNode* patch : patches)
|
|
|
- {
|
|
|
- patch->instances[instanceIndex]->setLocalTransform(trf);
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- ANKI_ASSERT(instanceIndex == 0);
|
|
|
-
|
|
|
- setLocalTransform(trf);
|
|
|
+ getSceneGraph().getPhysics().deletePhysicsObject(body);
|
|
|
}
|
|
|
}
|
|
|
|