Graphics/Renderable: Add InstanceData
Former-commit-id: f30f011ae91a445d5b22f33150a88bbda218950c
This commit is contained in:
parent
6f2f8d6390
commit
48a54dfa5c
|
|
@ -8,6 +8,7 @@
|
|||
#define NDK_COMPONENTS_GRAPHICSCOMPONENT_HPP
|
||||
|
||||
#include <Nazara/Graphics/Renderable.hpp>
|
||||
#include <Nazara/Utility/Node.hpp>
|
||||
#include <NDK/Component.hpp>
|
||||
|
||||
namespace Ndk
|
||||
|
|
@ -16,22 +17,49 @@ namespace Ndk
|
|||
{
|
||||
public:
|
||||
GraphicsComponent() = default;
|
||||
inline GraphicsComponent(const GraphicsComponent& graphicsComponent);
|
||||
~GraphicsComponent() = default;
|
||||
|
||||
inline void AddToRenderQueue(NzAbstractRenderQueue* renderQueue, const NzMatrix4f& transformMatrix) const;
|
||||
inline void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const;
|
||||
|
||||
inline void Attach(NzRenderableRef renderable);
|
||||
|
||||
inline void EnsureTransformMatrixUpdate() const;
|
||||
|
||||
static ComponentIndex componentIndex;
|
||||
|
||||
private:
|
||||
void InvalidateRenderableData(const NzRenderable* renderable, nzUInt32 flags, unsigned int index);
|
||||
inline void InvalidateTransformMatrix();
|
||||
|
||||
void OnAttached() override;
|
||||
void OnComponentAttached(BaseComponent& component) override;
|
||||
void OnComponentDetached(BaseComponent& component) override;
|
||||
void OnDetached() override;
|
||||
void OnNodeInvalidated(const NzNode* node);
|
||||
|
||||
void UpdateTransformMatrix() const;
|
||||
|
||||
NazaraSlot(NzNode, OnNodeInvalidation, m_nodeInvalidationSlot);
|
||||
|
||||
struct Renderable
|
||||
{
|
||||
NzBoundingVolumef volume;
|
||||
Renderable(NzMatrix4f& transformMatrix) :
|
||||
data(transformMatrix),
|
||||
dataUpdated(false)
|
||||
{
|
||||
}
|
||||
|
||||
NazaraSlot(NzRenderable, OnRenderableInvalidateInstanceData, renderableInvalidationSlot);
|
||||
|
||||
mutable NzRenderable::InstanceData data;
|
||||
NzRenderableRef renderable;
|
||||
mutable bool dataUpdated;
|
||||
};
|
||||
|
||||
std::vector<Renderable> m_renderables;
|
||||
mutable NzMatrix4f m_transformMatrix;
|
||||
mutable bool m_transformMatrixUpdated;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,16 +6,48 @@
|
|||
|
||||
namespace Ndk
|
||||
{
|
||||
inline void GraphicsComponent::AddToRenderQueue(NzAbstractRenderQueue* renderQueue, const NzMatrix4f& transformMatrix) const
|
||||
inline GraphicsComponent::GraphicsComponent(const GraphicsComponent& graphicsComponent) :
|
||||
Component(graphicsComponent),
|
||||
m_transformMatrix(graphicsComponent.m_transformMatrix),
|
||||
m_transformMatrixUpdated(graphicsComponent.m_transformMatrixUpdated)
|
||||
{
|
||||
m_renderables.reserve(graphicsComponent.m_renderables.size());
|
||||
for (const Renderable& r : graphicsComponent.m_renderables)
|
||||
Attach(r.renderable);
|
||||
}
|
||||
|
||||
inline void GraphicsComponent::AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const
|
||||
{
|
||||
EnsureTransformMatrixUpdate();
|
||||
|
||||
for (const Renderable& object : m_renderables)
|
||||
object.renderable->AddToRenderQueue(renderQueue, transformMatrix);
|
||||
{
|
||||
if (!object.dataUpdated)
|
||||
{
|
||||
object.renderable->UpdateData(&object.data);
|
||||
object.dataUpdated = true;
|
||||
}
|
||||
|
||||
object.renderable->AddToRenderQueue(renderQueue, object.data);
|
||||
}
|
||||
}
|
||||
|
||||
inline void GraphicsComponent::Attach(NzRenderableRef renderable)
|
||||
{
|
||||
m_renderables.resize(m_renderables.size() + 1);
|
||||
m_renderables.emplace_back(m_transformMatrix);
|
||||
Renderable& r = m_renderables.back();
|
||||
r.renderable = std::move(renderable);
|
||||
r.renderableInvalidationSlot.Connect(r.renderable->OnRenderableInvalidateInstanceData, std::bind(InvalidateRenderableData, this, std::placeholders::_1, std::placeholders::_2, m_renderables.size()-1));
|
||||
}
|
||||
|
||||
inline void GraphicsComponent::EnsureTransformMatrixUpdate() const
|
||||
{
|
||||
if (!m_transformMatrixUpdated)
|
||||
UpdateTransformMatrix();
|
||||
}
|
||||
|
||||
inline void GraphicsComponent::InvalidateTransformMatrix()
|
||||
{
|
||||
m_transformMatrixUpdated = false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,72 @@
|
|||
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
|
||||
|
||||
#include <NDK/Components/GraphicsComponent.hpp>
|
||||
#include <NDK/Components/NodeComponent.hpp>
|
||||
|
||||
namespace Ndk
|
||||
{
|
||||
void GraphicsComponent::InvalidateRenderableData(const NzRenderable* renderable, nzUInt32 flags, unsigned int index)
|
||||
{
|
||||
NazaraUnused(renderable);
|
||||
|
||||
NazaraAssert(index < m_renderables.size(), "Invalid renderable index");
|
||||
|
||||
Renderable& r = m_renderables[index];
|
||||
r.dataUpdated = false;
|
||||
r.renderable->InvalidateData(&r.data, flags);
|
||||
}
|
||||
|
||||
void GraphicsComponent::OnAttached()
|
||||
{
|
||||
if (m_entity->HasComponent<NodeComponent>())
|
||||
m_nodeInvalidationSlot.Connect(m_entity->GetComponent<NodeComponent>().OnNodeInvalidation, this, OnNodeInvalidated);
|
||||
|
||||
InvalidateTransformMatrix();
|
||||
}
|
||||
|
||||
void GraphicsComponent::OnComponentAttached(BaseComponent& component)
|
||||
{
|
||||
if (IsComponent<NodeComponent>(component))
|
||||
{
|
||||
NodeComponent& nodeComponent = static_cast<NodeComponent&>(component);
|
||||
m_nodeInvalidationSlot.Connect(nodeComponent.OnNodeInvalidation, this, OnNodeInvalidated);
|
||||
|
||||
InvalidateTransformMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsComponent::OnComponentDetached(BaseComponent& component)
|
||||
{
|
||||
if (IsComponent<NodeComponent>(component))
|
||||
{
|
||||
m_nodeInvalidationSlot.Disconnect();
|
||||
|
||||
InvalidateTransformMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsComponent::OnDetached()
|
||||
{
|
||||
m_nodeInvalidationSlot.Disconnect();
|
||||
|
||||
InvalidateTransformMatrix();
|
||||
}
|
||||
|
||||
void GraphicsComponent::OnNodeInvalidated(const NzNode* node)
|
||||
{
|
||||
NazaraUnused(node);
|
||||
|
||||
// Our view matrix depends on NodeComponent position/rotation
|
||||
InvalidateTransformMatrix();
|
||||
}
|
||||
|
||||
void GraphicsComponent::UpdateTransformMatrix() const
|
||||
{
|
||||
NazaraAssert(m_entity && m_entity->HasComponent<NodeComponent>(), "GraphicsComponent requires NodeComponent");
|
||||
|
||||
m_transformMatrix = m_entity->GetComponent<NodeComponent>().GetTransformMatrix();
|
||||
m_transformMatrixUpdated = true;
|
||||
}
|
||||
|
||||
ComponentIndex GraphicsComponent::componentIndex;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ namespace Ndk
|
|||
GraphicsComponent& graphicsComponent = drawable->GetComponent<GraphicsComponent>();
|
||||
NodeComponent& drawableNode = drawable->GetComponent<NodeComponent>();
|
||||
|
||||
graphicsComponent.AddToRenderQueue(renderQueue, drawableNode.GetTransformMatrix());
|
||||
graphicsComponent.AddToRenderQueue(renderQueue);
|
||||
}
|
||||
|
||||
NzColorBackground background;
|
||||
|
|
|
|||
|
|
@ -29,12 +29,12 @@ class NAZARA_API NzLight : public NzRenderable
|
|||
NzLight(const NzLight& light) = default;
|
||||
~NzLight() = default;
|
||||
|
||||
void AddToRenderQueue(NzAbstractRenderQueue* renderQueue, const NzMatrix4f& transformMatrix) const override;
|
||||
void AddToRenderQueue(NzAbstractRenderQueue* renderQueue, const InstanceData& instanceData) const override;
|
||||
|
||||
NzLight* Clone() const;
|
||||
NzLight* Create() const;
|
||||
|
||||
bool Cull(const NzFrustumf& frustum, const NzBoundingVolumef& volume, const NzMatrix4f& transformMatrix) const override;
|
||||
bool Cull(const NzFrustumf& frustum, const InstanceData& instanceData) const override;
|
||||
|
||||
float GetAmbientFactor() const;
|
||||
float GetAttenuation() const;
|
||||
|
|
@ -58,7 +58,7 @@ class NAZARA_API NzLight : public NzRenderable
|
|||
void SetOuterAngle(float outerAngle);
|
||||
void SetRadius(float radius);
|
||||
|
||||
void UpdateBoundingVolume(NzBoundingVolumef* boundingVolume, const NzMatrix4f& transformMatrix) const;
|
||||
void UpdateBoundingVolume(InstanceData* instanceData) const;
|
||||
|
||||
NzLight& operator=(const NzLight& light) = default;
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ class NAZARA_API NzModel : public NzRenderable, public NzResource
|
|||
NzModel(NzModel&& model) = default;
|
||||
virtual ~NzModel();
|
||||
|
||||
void AddToRenderQueue(NzAbstractRenderQueue* renderQueue, const NzMatrix4f& transformMatrix) const override;
|
||||
void AddToRenderQueue(NzAbstractRenderQueue* renderQueue, const InstanceData& instanceData) const override;
|
||||
|
||||
NzMaterial* GetMaterial(const NzString& subMeshName) const;
|
||||
NzMaterial* GetMaterial(unsigned int matIndex) const;
|
||||
|
|
|
|||
|
|
@ -27,25 +27,45 @@ using NzRenderableRef = NzObjectRef<NzRenderable>;
|
|||
class NAZARA_API NzRenderable : public NzRefCounted
|
||||
{
|
||||
public:
|
||||
struct InstanceData;
|
||||
|
||||
NzRenderable() = default;
|
||||
inline NzRenderable(const NzRenderable& renderable);
|
||||
virtual ~NzRenderable();
|
||||
|
||||
inline void EnsureBoundingVolumeUpdated() const;
|
||||
|
||||
virtual void AddToRenderQueue(NzAbstractRenderQueue* renderQueue, const NzMatrix4f& transformMatrix) const = 0;
|
||||
virtual bool Cull(const NzFrustumf& frustum, const NzBoundingVolumef& volume, const NzMatrix4f& transformMatrix) const;
|
||||
virtual void AddToRenderQueue(NzAbstractRenderQueue* renderQueue, const InstanceData& instanceData) const = 0;
|
||||
virtual bool Cull(const NzFrustumf& frustum, const InstanceData& instanceData) const;
|
||||
virtual const NzBoundingVolumef& GetBoundingVolume() const;
|
||||
virtual void UpdateBoundingVolume(NzBoundingVolumef* boundingVolume, const NzMatrix4f& transformMatrix) const;
|
||||
virtual void InvalidateData(InstanceData* instanceData, nzUInt32 flags) const;
|
||||
virtual void UpdateBoundingVolume(InstanceData* instanceData) const;
|
||||
virtual void UpdateData(InstanceData* instanceData) const;
|
||||
|
||||
inline NzRenderable& operator=(const NzRenderable& renderable);
|
||||
|
||||
// Signals:
|
||||
NazaraSignal(OnRenderableInvalidateInstanceData, const NzRenderable*, nzUInt32); //< Args: me, flags
|
||||
NazaraSignal(OnRenderableRelease, const NzRenderable*); //< Args: me
|
||||
|
||||
struct InstanceData
|
||||
{
|
||||
InstanceData(NzMatrix4f& referenceMatrix) :
|
||||
transformMatrix(referenceMatrix),
|
||||
flags(0)
|
||||
{
|
||||
}
|
||||
|
||||
std::vector<nzUInt8> data;
|
||||
NzBoundingVolumef volume;
|
||||
NzMatrix4f& transformMatrix;
|
||||
nzUInt32 flags;
|
||||
};
|
||||
|
||||
protected:
|
||||
virtual void MakeBoundingVolume() const = 0;
|
||||
void InvalidateBoundingVolume();
|
||||
inline void InvalidateInstanceData(nzUInt32 flags);
|
||||
inline void UpdateBoundingVolume() const;
|
||||
|
||||
mutable NzBoundingVolumef m_boundingVolume;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,11 @@ inline void NzRenderable::InvalidateBoundingVolume()
|
|||
m_boundingVolumeUpdated = false;
|
||||
}
|
||||
|
||||
inline void NzRenderable::InvalidateInstanceData(nzUInt32 flags)
|
||||
{
|
||||
OnRenderableInvalidateInstanceData(this, flags);
|
||||
}
|
||||
|
||||
inline NzRenderable& NzRenderable::operator=(const NzRenderable& renderable)
|
||||
{
|
||||
m_boundingVolume = renderable.m_boundingVolume;
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ class NAZARA_API NzSkeletalModel : public NzModel, NzUpdatable
|
|||
NzSkeletalModel(NzSkeletalModel&& model) = default;
|
||||
~NzSkeletalModel() = default;
|
||||
|
||||
void AddToRenderQueue(NzAbstractRenderQueue* renderQueue, const NzMatrix4f& transformMatrix) const override;
|
||||
void AddToRenderQueue(NzAbstractRenderQueue* renderQueue, const InstanceData& instanceData) const override;
|
||||
void AdvanceAnimation(float elapsedTime);
|
||||
|
||||
NzSkeletalModel* Clone() const;
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ m_type(type)
|
|||
SetRadius(5.f);
|
||||
}
|
||||
|
||||
void NzLight::AddToRenderQueue(NzAbstractRenderQueue* renderQueue, const NzMatrix4f& transformMatrix) const
|
||||
void NzLight::AddToRenderQueue(NzAbstractRenderQueue* renderQueue, const InstanceData& instanceData) const
|
||||
{
|
||||
switch (m_type)
|
||||
{
|
||||
|
|
@ -38,7 +38,7 @@ void NzLight::AddToRenderQueue(NzAbstractRenderQueue* renderQueue, const NzMatri
|
|||
light.ambientFactor = m_ambientFactor;
|
||||
light.color = m_color;
|
||||
light.diffuseFactor = m_diffuseFactor;
|
||||
light.direction = transformMatrix.Transform(NzVector3f::Forward(), 0.f);
|
||||
light.direction = instanceData.transformMatrix.Transform(NzVector3f::Forward(), 0.f);
|
||||
|
||||
renderQueue->AddDirectionalLight(light);
|
||||
break;
|
||||
|
|
@ -52,7 +52,7 @@ void NzLight::AddToRenderQueue(NzAbstractRenderQueue* renderQueue, const NzMatri
|
|||
light.color = m_color;
|
||||
light.diffuseFactor = m_diffuseFactor;
|
||||
light.invRadius = m_invRadius;
|
||||
light.position = transformMatrix.GetTranslation();
|
||||
light.position = instanceData.transformMatrix.GetTranslation();
|
||||
light.radius = m_radius;
|
||||
|
||||
renderQueue->AddPointLight(light);
|
||||
|
|
@ -66,12 +66,12 @@ void NzLight::AddToRenderQueue(NzAbstractRenderQueue* renderQueue, const NzMatri
|
|||
light.attenuation = m_attenuation;
|
||||
light.color = m_color;
|
||||
light.diffuseFactor = m_diffuseFactor;
|
||||
light.direction = transformMatrix.Transform(NzVector3f::Forward(), 0.f);
|
||||
light.direction = instanceData.transformMatrix.Transform(NzVector3f::Forward(), 0.f);
|
||||
light.innerAngleCosine = m_innerAngleCosine;
|
||||
light.invRadius = m_invRadius;
|
||||
light.outerAngleCosine = m_outerAngleCosine;
|
||||
light.outerAngleTangent = m_outerAngleTangent;
|
||||
light.position = transformMatrix.GetTranslation();
|
||||
light.position = instanceData.transformMatrix.GetTranslation();
|
||||
light.radius = m_radius;
|
||||
|
||||
renderQueue->AddSpotLight(light);
|
||||
|
|
@ -94,7 +94,7 @@ NzLight* NzLight::Create() const
|
|||
return new NzLight;
|
||||
}
|
||||
|
||||
bool NzLight::Cull(const NzFrustumf& frustum, const NzBoundingVolumef& volume, const NzMatrix4f& transformMatrix) const
|
||||
bool NzLight::Cull(const NzFrustumf& frustum, const InstanceData& instanceData) const
|
||||
{
|
||||
switch (m_type)
|
||||
{
|
||||
|
|
@ -102,19 +102,19 @@ bool NzLight::Cull(const NzFrustumf& frustum, const NzBoundingVolumef& volume, c
|
|||
return true; // Always visible
|
||||
|
||||
case nzLightType_Point:
|
||||
return frustum.Contains(NzSpheref(transformMatrix.GetTranslation(), m_radius)); // A sphere test is much faster (and precise)
|
||||
return frustum.Contains(NzSpheref(instanceData.transformMatrix.GetTranslation(), m_radius)); // A sphere test is much faster (and precise)
|
||||
|
||||
case nzLightType_Spot:
|
||||
return frustum.Contains(volume);
|
||||
return frustum.Contains(instanceData.volume);
|
||||
}
|
||||
|
||||
NazaraError("Invalid light type (0x" + NzString::Number(m_type, 16) + ')');
|
||||
return false;
|
||||
}
|
||||
|
||||
void NzLight::UpdateBoundingVolume(NzBoundingVolumef* boundingVolume, const NzMatrix4f& transformMatrix) const
|
||||
void NzLight::UpdateBoundingVolume(InstanceData* instanceData) const
|
||||
{
|
||||
NazaraAssert(boundingVolume, "Invalid bounding volume");
|
||||
NazaraAssert(instanceData, "Invalid data");
|
||||
|
||||
switch (m_type)
|
||||
{
|
||||
|
|
@ -122,11 +122,11 @@ void NzLight::UpdateBoundingVolume(NzBoundingVolumef* boundingVolume, const NzMa
|
|||
break; // Nothing to do (bounding volume should be infinite)
|
||||
|
||||
case nzLightType_Point:
|
||||
boundingVolume->Update(transformMatrix.GetTranslation()); // The bounding volume only needs to be shifted
|
||||
instanceData->volume.Update(instanceData->transformMatrix.GetTranslation()); // The bounding volume only needs to be shifted
|
||||
break;
|
||||
|
||||
case nzLightType_Spot:
|
||||
boundingVolume->Update(transformMatrix);
|
||||
instanceData->volume.Update(instanceData->transformMatrix);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ NzModel::~NzModel()
|
|||
Reset();
|
||||
}
|
||||
|
||||
void NzModel::AddToRenderQueue(NzAbstractRenderQueue* renderQueue, const NzMatrix4f& transformMatrix) const
|
||||
void NzModel::AddToRenderQueue(NzAbstractRenderQueue* renderQueue, const InstanceData& instanceData) const
|
||||
{
|
||||
unsigned int submeshCount = m_mesh->GetSubMeshCount();
|
||||
for (unsigned int i = 0; i < submeshCount; ++i)
|
||||
|
|
@ -49,7 +49,7 @@ void NzModel::AddToRenderQueue(NzAbstractRenderQueue* renderQueue, const NzMatri
|
|||
meshData.primitiveMode = mesh->GetPrimitiveMode();
|
||||
meshData.vertexBuffer = mesh->GetVertexBuffer();
|
||||
|
||||
renderQueue->AddMesh(material, meshData, mesh->GetAABB(), transformMatrix);
|
||||
renderQueue->AddMesh(material, meshData, mesh->GetAABB(), instanceData.transformMatrix);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,11 +10,9 @@ NzRenderable::~NzRenderable()
|
|||
OnRenderableRelease(this);
|
||||
}
|
||||
|
||||
bool NzRenderable::Cull(const NzFrustumf& frustum, const NzBoundingVolumef& volume, const NzMatrix4f& transformMatrix) const
|
||||
bool NzRenderable::Cull(const NzFrustumf& frustum, const InstanceData& instanceData) const
|
||||
{
|
||||
NazaraUnused(transformMatrix);
|
||||
|
||||
return frustum.Contains(volume);
|
||||
return frustum.Contains(instanceData.volume);
|
||||
}
|
||||
|
||||
const NzBoundingVolumef& NzRenderable::GetBoundingVolume() const
|
||||
|
|
@ -24,11 +22,22 @@ const NzBoundingVolumef& NzRenderable::GetBoundingVolume() const
|
|||
return m_boundingVolume;
|
||||
}
|
||||
|
||||
void NzRenderable::UpdateBoundingVolume(NzBoundingVolumef* boundingVolume, const NzMatrix4f& transformMatrix) const
|
||||
void NzRenderable::InvalidateData(InstanceData* instanceData, nzUInt32 flags) const
|
||||
{
|
||||
NazaraAssert(boundingVolume, "Invalid bounding volume");
|
||||
instanceData->flags |= flags;
|
||||
}
|
||||
|
||||
boundingVolume->Update(transformMatrix);
|
||||
void NzRenderable::UpdateBoundingVolume(InstanceData* instanceData) const
|
||||
{
|
||||
NazaraAssert(instanceData, "Invalid instance data");
|
||||
NazaraUnused(instanceData);
|
||||
|
||||
instanceData->volume.Update(instanceData->transformMatrix);
|
||||
}
|
||||
|
||||
void NzRenderable::UpdateData(InstanceData* instanceData) const
|
||||
{
|
||||
NazaraAssert(instanceData, "Invalid instance data");
|
||||
}
|
||||
|
||||
NzRenderableLibrary::LibraryMap NzRenderable::s_library;
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ m_animationEnabled(true)
|
|||
{
|
||||
}
|
||||
|
||||
void NzSkeletalModel::AddToRenderQueue(NzAbstractRenderQueue* renderQueue, const NzMatrix4f& transformMatrix) const
|
||||
void NzSkeletalModel::AddToRenderQueue(NzAbstractRenderQueue* renderQueue, const InstanceData& instanceData) const
|
||||
{
|
||||
if (!m_mesh)
|
||||
return;
|
||||
|
|
@ -47,7 +47,7 @@ void NzSkeletalModel::AddToRenderQueue(NzAbstractRenderQueue* renderQueue, const
|
|||
meshData.primitiveMode = mesh->GetPrimitiveMode();
|
||||
meshData.vertexBuffer = NzSkinningManager::GetBuffer(mesh, &m_skeleton);
|
||||
|
||||
renderQueue->AddMesh(material, meshData, m_skeleton.GetAABB(), transformMatrix);
|
||||
renderQueue->AddMesh(material, meshData, m_skeleton.GetAABB(), instanceData.transformMatrix);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue