Add initial support for skeletal entities / components

This commit is contained in:
SirLynix
2022-08-27 03:07:48 +02:00
parent 01f3f350fe
commit 50ed8b4028
55 changed files with 919 additions and 131 deletions

View File

@@ -69,6 +69,7 @@
#include <Nazara/Graphics/RenderQueueRegistry.hpp>
#include <Nazara/Graphics/RenderSpriteChain.hpp>
#include <Nazara/Graphics/RenderSubmesh.hpp>
#include <Nazara/Graphics/SkeletonInstance.hpp>
#include <Nazara/Graphics/SlicedSprite.hpp>
#include <Nazara/Graphics/SpotLight.hpp>
#include <Nazara/Graphics/Sprite.hpp>

View File

@@ -23,7 +23,7 @@ namespace Nz
struct Renderable;
static constexpr std::size_t MaxRenderableCount = 8;
inline GraphicsComponent(bool initialyVisible = true);
inline GraphicsComponent(bool initiallyVisible = true);
GraphicsComponent(const GraphicsComponent&) = default;
GraphicsComponent(GraphicsComponent&&) = default;
~GraphicsComponent() = default;

View File

@@ -7,9 +7,9 @@
namespace Nz
{
inline GraphicsComponent::GraphicsComponent(bool initialyVisible) :
inline GraphicsComponent::GraphicsComponent(bool initiallyVisible) :
m_scissorBox(-1, -1, -1, -1),
m_isVisible(initialyVisible)
m_isVisible(initiallyVisible)
{
m_worldInstance = std::make_shared<WorldInstance>(); //< FIXME: Use pools
}

View File

@@ -42,12 +42,14 @@ namespace Nz
ForwardFramePipeline(ForwardFramePipeline&&) = delete;
~ForwardFramePipeline();
void InvalidateSkeletalInstance(std::size_t skeletalInstanceIndex) override;
void InvalidateViewer(std::size_t viewerIndex) override;
void InvalidateWorldInstance(std::size_t renderableIndex) override;
std::size_t RegisterLight(std::shared_ptr<Light> light, UInt32 renderMask) override;
void RegisterMaterialPass(MaterialPass* materialPass) override;
std::size_t RegisterRenderable(std::size_t worldInstanceIndex, const InstancedRenderable* instancedRenderable, UInt32 renderMask, const Recti& scissorBox) override;
std::size_t RegisterRenderable(std::size_t worldInstanceIndex, std::size_t skeletonInstanceIndex, const InstancedRenderable* instancedRenderable, UInt32 renderMask, const Recti& scissorBox) override;
std::size_t RegisterSkeleton(SkeletonInstancePtr skeletonInstance) override;
std::size_t RegisterViewer(AbstractViewer* viewerInstance, Int32 renderOrder) override;
std::size_t RegisterWorldInstance(WorldInstancePtr worldInstance) override;
@@ -56,6 +58,7 @@ namespace Nz
void UnregisterLight(std::size_t lightIndex) override;
void UnregisterMaterialPass(MaterialPass* material) override;
void UnregisterRenderable(std::size_t renderableIndex) override;
void UnregisterSkeleton(std::size_t skeletonIndex) override;
void UnregisterViewer(std::size_t viewerIndex) override;
void UnregisterWorldInstance(std::size_t worldInstance) override;
@@ -89,6 +92,7 @@ namespace Nz
struct RenderableData
{
std::size_t skeletonInstanceIndex;
std::size_t worldInstanceIndex;
const InstancedRenderable* renderable;
Recti scissorBox;
@@ -127,11 +131,15 @@ namespace Nz
std::vector<FramePipelinePass::VisibleRenderable> m_visibleRenderables;
std::vector<const Light*> m_visibleLights;
BakedFrameGraph m_bakedFrameGraph;
Bitset<UInt64> m_invalidatedSkeletonInstances;
Bitset<UInt64> m_invalidatedViewerInstances;
Bitset<UInt64> m_invalidatedWorldInstances;
Bitset<UInt64> m_removedSkeletonInstances;
Bitset<UInt64> m_removedViewerInstances;
Bitset<UInt64> m_removedWorldInstances;
MemoryPool<RenderableData> m_renderablePool;
MemoryPool<LightData> m_lightPool;
MemoryPool<SkeletonInstancePtr> m_skeletonInstances;
MemoryPool<ViewerData> m_viewerPool;
MemoryPool<WorldInstancePtr> m_worldInstances;
RenderFrame* m_currentRenderFrame;

View File

@@ -11,6 +11,7 @@
#include <Nazara/Graphics/Config.hpp>
#include <Nazara/Graphics/RenderElement.hpp>
#include <Nazara/Graphics/RenderQueue.hpp>
#include <Nazara/Graphics/SkeletonInstance.hpp>
#include <Nazara/Graphics/WorldInstance.hpp>
#include <Nazara/Renderer/DebugDrawer.hpp>
#include <memory>
@@ -39,14 +40,16 @@ namespace Nz
inline ElementRenderer& GetElementRenderer(std::size_t elementIndex);
inline std::size_t GetElementRendererCount() const;
virtual void InvalidateSkeletalInstance(std::size_t skeletalInstanceIndex) = 0;
virtual void InvalidateViewer(std::size_t viewerIndex) = 0;
virtual void InvalidateWorldInstance(std::size_t) = 0;
virtual void InvalidateWorldInstance(std::size_t worldInstance) = 0;
template<typename F> void ProcessRenderQueue(const RenderQueue<RenderElement*>& renderQueue, F&& callback);
virtual std::size_t RegisterLight(std::shared_ptr<Light> light, UInt32 renderMask) = 0;
virtual void RegisterMaterialPass(MaterialPass* materialPass) = 0;
virtual std::size_t RegisterRenderable(std::size_t worldInstanceIndex, const InstancedRenderable* instancedRenderable, UInt32 renderMask, const Recti& scissorBox) = 0;
virtual std::size_t RegisterRenderable(std::size_t worldInstanceIndex, std::size_t skeletonInstanceIndex, const InstancedRenderable* instancedRenderable, UInt32 renderMask, const Recti& scissorBox) = 0;
virtual std::size_t RegisterSkeleton(SkeletonInstancePtr skeletonInstance) = 0;
virtual std::size_t RegisterViewer(AbstractViewer* viewerInstance, Int32 renderOrder) = 0;
virtual std::size_t RegisterWorldInstance(WorldInstancePtr worldInstance) = 0;
@@ -55,6 +58,7 @@ namespace Nz
virtual void UnregisterLight(std::size_t lightIndex) = 0;
virtual void UnregisterMaterialPass(MaterialPass* materialPass) = 0;
virtual void UnregisterRenderable(std::size_t renderableIndex) = 0;
virtual void UnregisterSkeleton(std::size_t skeletonIndex) = 0;
virtual void UnregisterViewer(std::size_t viewerIndex) = 0;
virtual void UnregisterWorldInstance(std::size_t worldInstance) = 0;
@@ -68,6 +72,8 @@ namespace Nz
NazaraSignal(OnTransfer, FramePipeline* /*pipeline*/, RenderFrame& /*renderFrame*/, CommandBufferBuilder& /*builder*/);
static constexpr std::size_t NoSkeletonInstance = std::numeric_limits<std::size_t>::max();
private:
std::vector<std::unique_ptr<ElementRenderer>> m_elementRenderers;
DebugDrawer m_debugDrawer;

View File

@@ -14,6 +14,7 @@
namespace Nz
{
class InstancedRenderable;
class SkeletonInstance;
class WorldInstance;
class NAZARA_GRAPHICS_API FramePipelinePass
@@ -30,6 +31,7 @@ namespace Nz
struct VisibleRenderable
{
const InstancedRenderable* instancedRenderable;
const SkeletonInstance* skeletonInstance;
const WorldInstance* worldInstance;
Recti scissorBox;
};

View File

@@ -18,6 +18,7 @@ namespace Nz
class CommandBufferBuilder;
class Material;
class RenderElement;
class SkeletonInstance;
class WorldInstance;
class NAZARA_GRAPHICS_API InstancedRenderable
@@ -28,7 +29,7 @@ namespace Nz
InstancedRenderable(InstancedRenderable&&) noexcept = default;
~InstancedRenderable();
virtual void BuildElement(std::size_t passIndex, const WorldInstance& worldInstance, std::vector<std::unique_ptr<RenderElement>>& elements, const Recti& scissorBox) const = 0;
virtual void BuildElement(std::size_t passIndex, const WorldInstance& worldInstance, const SkeletonInstance* skeletonInstance, std::vector<std::unique_ptr<RenderElement>>& elements, const Recti& scissorBox) const = 0;
inline const Boxf& GetAABB() const;
virtual const std::shared_ptr<Material>& GetMaterial(std::size_t i) const = 0;

View File

@@ -30,7 +30,7 @@ namespace Nz
inline void AddSection(float size, float textureCoord);
void BuildElement(std::size_t passIndex, const WorldInstance& worldInstance, std::vector<std::unique_ptr<RenderElement>>& elements, const Recti& scissorBox) const override;
void BuildElement(std::size_t passIndex, const WorldInstance& worldInstance, const SkeletonInstance* skeletonInstance, std::vector<std::unique_ptr<RenderElement>>& elements, const Recti& scissorBox) const override;
inline void Clear();

View File

@@ -28,7 +28,7 @@ namespace Nz
Model(Model&&) noexcept = default;
~Model() = default;
void BuildElement(std::size_t passIndex, const WorldInstance& worldInstance, std::vector<std::unique_ptr<RenderElement>>& elements, const Recti& scissorBox) const override;
void BuildElement(std::size_t passIndex, const WorldInstance& worldInstance, const SkeletonInstance* skeletonInstance, std::vector<std::unique_ptr<RenderElement>>& elements, const Recti& scissorBox) const override;
const std::shared_ptr<RenderBuffer>& GetIndexBuffer(std::size_t subMeshIndex) const;
std::size_t GetIndexCount(std::size_t subMeshIndex) const;

View File

@@ -15,6 +15,7 @@ namespace Nz
{
class MaterialPass;
class RenderPipeline;
class Skeleton;
class VertexDeclaration;
class RenderQueueRegistry
@@ -28,6 +29,7 @@ namespace Nz
inline std::size_t FetchLayerIndex(int renderLayer) const;
inline std::size_t FetchMaterialPassIndex(const MaterialPass* materialPass) const;
inline std::size_t FetchPipelineIndex(const RenderPipeline* pipeline) const;
inline std::size_t FetchSkeletonIndex(const Skeleton* skeleton) const;
inline std::size_t FetchVertexBuffer(const RenderBuffer* vertexBuffer) const;
inline std::size_t FetchVertexDeclaration(const VertexDeclaration* vertexDeclaration) const;
@@ -36,6 +38,7 @@ namespace Nz
inline void RegisterLayer(int renderLayer);
inline void RegisterMaterialPass(const MaterialPass* materialPass);
inline void RegisterPipeline(const RenderPipeline* pipeline);
inline void RegisterSkeleton(const Skeleton* skeleton);
inline void RegisterVertexBuffer(const RenderBuffer* vertexBuffer);
inline void RegisterVertexDeclaration(const VertexDeclaration* vertexDeclaration);
@@ -45,6 +48,7 @@ namespace Nz
robin_hood::unordered_map<const MaterialPass*, std::size_t> m_materialPassRegistry;
robin_hood::unordered_map<const RenderPipeline*, std::size_t> m_pipelineRegistry;
robin_hood::unordered_map<const RenderBuffer*, std::size_t> m_vertexBufferRegistry;
robin_hood::unordered_map<const Skeleton*, std::size_t> m_skeletonRegistry;
robin_hood::unordered_map<const VertexDeclaration*, std::size_t> m_vertexDeclarationRegistry;
};
}

View File

@@ -42,6 +42,14 @@ namespace Nz
return it->second;
}
inline std::size_t RenderQueueRegistry::FetchSkeletonIndex(const Skeleton* skeleton) const
{
auto it = m_skeletonRegistry.find(skeleton);
assert(it != m_skeletonRegistry.end());
return it->second;
}
inline std::size_t RenderQueueRegistry::FetchVertexBuffer(const RenderBuffer* vertexBuffer) const
{
auto it = m_vertexBufferRegistry.find(vertexBuffer);
@@ -80,6 +88,11 @@ namespace Nz
m_pipelineRegistry.try_emplace(pipeline, m_pipelineRegistry.size());
}
inline void RenderQueueRegistry::RegisterSkeleton(const Skeleton* skeleton)
{
m_skeletonRegistry.try_emplace(skeleton, m_skeletonRegistry.size());
}
inline void RenderQueueRegistry::RegisterVertexBuffer(const RenderBuffer* vertexBuffer)
{
m_vertexBufferRegistry.try_emplace(vertexBuffer, m_vertexBufferRegistry.size());

View File

@@ -10,6 +10,7 @@
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Graphics/RenderElement.hpp>
#include <Nazara/Graphics/RenderQueueRegistry.hpp>
#include <Nazara/Graphics/SkeletonInstance.hpp>
#include <Nazara/Graphics/WorldInstance.hpp>
#include <memory>
#include <vector>
@@ -23,7 +24,7 @@ namespace Nz
class RenderSubmesh : public RenderElement
{
public:
inline RenderSubmesh(int renderLayer, std::shared_ptr<MaterialPass> materialPass, std::shared_ptr<RenderPipeline> renderPipeline, const WorldInstance& worldInstance, std::size_t indexCount, IndexType indexType, std::shared_ptr<RenderBuffer> indexBuffer, std::shared_ptr<RenderBuffer> vertexBuffer, const Recti& scissorBox);
inline RenderSubmesh(int renderLayer, std::shared_ptr<MaterialPass> materialPass, std::shared_ptr<RenderPipeline> renderPipeline, const WorldInstance& worldInstance, const SkeletonInstance* skeletonInstance, std::size_t indexCount, IndexType indexType, std::shared_ptr<RenderBuffer> indexBuffer, std::shared_ptr<RenderBuffer> vertexBuffer, const Recti& scissorBox);
~RenderSubmesh() = default;
inline UInt64 ComputeSortingScore(const Frustumf& frustum, const RenderQueueRegistry& registry) const override;
@@ -34,6 +35,7 @@ namespace Nz
inline const MaterialPass& GetMaterialPass() const;
inline const RenderPipeline* GetRenderPipeline() const;
inline const Recti& GetScissorBox() const;
inline const SkeletonInstance* GetSkeletonInstance() const;
inline const RenderBuffer* GetVertexBuffer() const;
inline const WorldInstance& GetWorldInstance() const;
@@ -45,6 +47,7 @@ namespace Nz
std::shared_ptr<MaterialPass> m_materialPass;
std::shared_ptr<RenderPipeline> m_renderPipeline;
std::size_t m_indexCount;
const SkeletonInstance* m_skeletonInstance;
const WorldInstance& m_worldInstance;
IndexType m_indexType;
Recti m_scissorBox;

View File

@@ -9,13 +9,14 @@
namespace Nz
{
inline RenderSubmesh::RenderSubmesh(int renderLayer, std::shared_ptr<MaterialPass> materialPass, std::shared_ptr<RenderPipeline> renderPipeline, const WorldInstance& worldInstance, std::size_t indexCount, IndexType indexType, std::shared_ptr<RenderBuffer> indexBuffer, std::shared_ptr<RenderBuffer> vertexBuffer, const Recti& scissorBox) :
inline RenderSubmesh::RenderSubmesh(int renderLayer, std::shared_ptr<MaterialPass> materialPass, std::shared_ptr<RenderPipeline> renderPipeline, const WorldInstance& worldInstance, const SkeletonInstance* skeletonInstance, std::size_t indexCount, IndexType indexType, std::shared_ptr<RenderBuffer> indexBuffer, std::shared_ptr<RenderBuffer> vertexBuffer, const Recti& scissorBox) :
RenderElement(BasicRenderElement::Submesh),
m_indexBuffer(std::move(indexBuffer)),
m_vertexBuffer(std::move(vertexBuffer)),
m_materialPass(std::move(materialPass)),
m_renderPipeline(std::move(renderPipeline)),
m_indexCount(indexCount),
m_skeletonInstance(skeletonInstance),
m_worldInstance(worldInstance),
m_indexType(indexType),
m_scissorBox(scissorBox),
@@ -51,6 +52,10 @@ namespace Nz
UInt64 pipelineIndex = registry.FetchPipelineIndex(m_renderPipeline.get());
UInt64 vertexBufferIndex = registry.FetchVertexBuffer(m_vertexBuffer.get());
UInt64 skeletonIndex = 0;
if (m_skeletonInstance)
skeletonIndex = registry.FetchSkeletonIndex(m_skeletonInstance->GetSkeleton().get());
UInt64 matFlags = 0;
// Opaque RQ index:
@@ -60,14 +65,15 @@ namespace Nz
// - Pipeline (16bits)
// - MaterialPass (16bits)
// - VertexBuffer (8bits)
// - ?? (8bits) - Depth?
// - Skeleton (8bits)
return (layerIndex & 0xFF) << 60 |
(matFlags) << 52 |
(elementType & 0xF) << 51 |
(pipelineIndex & 0xFFFF) << 35 |
(materialPassIndex & 0xFFFF) << 23 |
(vertexBufferIndex & 0xFF) << 7;
(vertexBufferIndex & 0xFF) << 7 |
(skeletonIndex & 0xFF);
}
}
@@ -101,6 +107,11 @@ namespace Nz
return m_scissorBox;
}
inline const SkeletonInstance* RenderSubmesh::GetSkeletonInstance() const
{
return m_skeletonInstance;
}
inline const RenderBuffer* RenderSubmesh::GetVertexBuffer() const
{
return m_vertexBuffer.get();
@@ -117,6 +128,8 @@ namespace Nz
registry.RegisterMaterialPass(m_materialPass.get());
registry.RegisterPipeline(m_renderPipeline.get());
registry.RegisterVertexBuffer(m_vertexBuffer.get());
if (m_skeletonInstance)
registry.RegisterSkeleton(m_skeletonInstance->GetSkeleton().get());
}
}

View File

@@ -0,0 +1,54 @@
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_GRAPHICS_SKELETONINSTANCE_HPP
#define NAZARA_GRAPHICS_SKELETONINSTANCE_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Graphics/Config.hpp>
#include <Nazara/Math/Matrix4.hpp>
#include <Nazara/Renderer/ShaderBinding.hpp>
#include <Nazara/Utility/Skeleton.hpp>
#include <memory>
namespace Nz
{
class CommandBufferBuilder;
class RenderBuffer;
class SkeletonInstance;
class UploadPool;
using SkeletonInstancePtr = std::shared_ptr<SkeletonInstance>;
class NAZARA_GRAPHICS_API SkeletonInstance
{
public:
SkeletonInstance(std::shared_ptr<const Skeleton> skeleton);
SkeletonInstance(const SkeletonInstance&) = delete;
SkeletonInstance(SkeletonInstance&& skeletonInstance) noexcept;
~SkeletonInstance() = default;
inline std::shared_ptr<RenderBuffer>& GetSkeletalBuffer();
inline const std::shared_ptr<RenderBuffer>& GetSkeletalBuffer() const;
inline const std::shared_ptr<const Skeleton>& GetSkeleton() const;
void UpdateBuffers(UploadPool& uploadPool, CommandBufferBuilder& builder);
SkeletonInstance& operator=(const SkeletonInstance&) = delete;
SkeletonInstance& operator=(SkeletonInstance&& skeletonInstance) noexcept;
private:
NazaraSlot(Skeleton, OnSkeletonJointsInvalidated, m_onSkeletonJointsInvalidated);
std::shared_ptr<RenderBuffer> m_skeletalDataBuffer;
std::shared_ptr<const Skeleton> m_skeleton;
bool m_dataInvalided;
};
}
#include <Nazara/Graphics/SkeletonInstance.inl>
#endif // NAZARA_GRAPHICS_SKELETONINSTANCE_HPP

View File

@@ -0,0 +1,26 @@
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/SkeletonInstance.hpp>
#include <Nazara/Graphics/Debug.hpp>
namespace Nz
{
inline std::shared_ptr<RenderBuffer>& SkeletonInstance::GetSkeletalBuffer()
{
return m_skeletalDataBuffer;
}
inline const std::shared_ptr<RenderBuffer>& SkeletonInstance::GetSkeletalBuffer() const
{
return m_skeletalDataBuffer;
}
inline const std::shared_ptr<const Skeleton>& SkeletonInstance::GetSkeleton() const
{
return m_skeleton;
}
}
#include <Nazara/Graphics/DebugOff.hpp>

View File

@@ -27,7 +27,7 @@ namespace Nz
SlicedSprite(SlicedSprite&&) noexcept = default;
~SlicedSprite() = default;
void BuildElement(std::size_t passIndex, const WorldInstance& worldInstance, std::vector<std::unique_ptr<RenderElement>>& elements, const Recti& scissorBox) const override;
void BuildElement(std::size_t passIndex, const WorldInstance& worldInstance, const SkeletonInstance* skeletonInstance, std::vector<std::unique_ptr<RenderElement>>& elements, const Recti& scissorBox) const override;
inline const Color& GetColor() const;
inline const Corner& GetBottomRightCorner() const;

View File

@@ -25,7 +25,7 @@ namespace Nz
Sprite(Sprite&&) noexcept = default;
~Sprite() = default;
void BuildElement(std::size_t passIndex, const WorldInstance& worldInstance, std::vector<std::unique_ptr<RenderElement>>& elements, const Recti& scissorBox) const override;
void BuildElement(std::size_t passIndex, const WorldInstance& worldInstance, const SkeletonInstance* skeletonInstance, std::vector<std::unique_ptr<RenderElement>>& elements, const Recti& scissorBox) const override;
inline const Color& GetColor() const;
inline const Color& GetCornerColor(RectCorner corner) const;

View File

@@ -12,6 +12,7 @@
#include <Nazara/Graphics/Components/GraphicsComponent.hpp>
#include <Nazara/Graphics/Components/LightComponent.hpp>
#include <Nazara/Utility/Node.hpp>
#include <Nazara/Utility/Skeleton.hpp>
#include <Nazara/Utils/MemoryPool.hpp>
#include <entt/entt.hpp>
#include <array>
@@ -53,10 +54,14 @@ namespace Nz
void OnGraphicsDestroy(entt::registry& registry, entt::entity entity);
void OnLightDestroy(entt::registry& registry, entt::entity entity);
void OnNodeDestroy(entt::registry& registry, entt::entity entity);
void OnSharedSkeletonDestroy(entt::registry& registry, entt::entity entity);
void OnSkeletonDestroy(entt::registry& registry, entt::entity entity);
void UpdateInstances();
void UpdateObservers();
void UpdateVisibility();
static constexpr std::size_t NoInstance = std::numeric_limits<std::size_t>::max();
struct CameraEntity
{
entt::entity entity;
@@ -71,6 +76,7 @@ namespace Nz
entt::entity entity;
std::array<std::size_t, GraphicsComponent::MaxRenderableCount> renderableIndices;
std::size_t poolIndex;
std::size_t skeletonInstanceIndex;
std::size_t worldInstanceIndex;
NazaraSlot(GraphicsComponent, OnRenderableAttached, onRenderableAttached);
@@ -78,6 +84,7 @@ namespace Nz
NazaraSlot(GraphicsComponent, OnScissorBoxUpdate, onScissorBoxUpdate);
NazaraSlot(GraphicsComponent, OnVisibilityUpdate, onVisibilityUpdate);
NazaraSlot(Node, OnNodeInvalidation, onNodeInvalidation);
NazaraSlot(Skeleton, OnSkeletonJointsInvalidated, onSkeletonJointsInvalidated); //< only connected for owned skeleton
};
struct LightEntity
@@ -92,14 +99,26 @@ namespace Nz
NazaraSlot(Node, OnNodeInvalidation, onNodeInvalidation);
};
entt::connection m_cameraDestroyConnection;
entt::connection m_graphicsDestroyConnection;
entt::connection m_lightDestroyConnection;
entt::connection m_nodeDestroyConnection;
struct SharedSkeleton
{
std::size_t skeletonInstanceIndex;
std::size_t useCount;
NazaraSlot(Skeleton, OnSkeletonJointsInvalidated, onJointsInvalidated);
};
entt::registry& m_registry;
entt::observer m_cameraConstructObserver;
entt::observer m_graphicsConstructObserver;
entt::observer m_lightConstructObserver;
entt::registry& m_registry;
entt::observer m_sharedSkeletonConstructObserver;
entt::observer m_skeletonConstructObserver;
entt::scoped_connection m_cameraDestroyConnection;
entt::scoped_connection m_graphicsDestroyConnection;
entt::scoped_connection m_lightDestroyConnection;
entt::scoped_connection m_nodeDestroyConnection;
entt::scoped_connection m_sharedSkeletonDestroyConnection;
entt::scoped_connection m_skeletonDestroyConnection;
std::set<CameraEntity*> m_invalidatedCameraNode;
std::set<GraphicsEntity*> m_invalidatedGfxWorldNode;
std::set<LightEntity*> m_invalidatedLightWorldNode;
@@ -107,6 +126,7 @@ namespace Nz
std::unordered_map<entt::entity, CameraEntity*> m_cameraEntities;
std::unordered_map<entt::entity, GraphicsEntity*> m_graphicsEntities;
std::unordered_map<entt::entity, LightEntity*> m_lightEntities;
std::unordered_map<Skeleton*, SharedSkeleton> m_sharedSkeletonInstances;
std::unordered_set<GraphicsEntity*> m_newlyHiddenGfxEntities;
std::unordered_set<GraphicsEntity*> m_newlyVisibleGfxEntities;
std::unordered_set<LightEntity*> m_newlyHiddenLightEntities;

View File

@@ -28,7 +28,7 @@ namespace Nz
TextSprite(TextSprite&&) noexcept = default;
~TextSprite() = default;
void BuildElement(std::size_t passIndex, const WorldInstance& worldInstance, std::vector<std::unique_ptr<RenderElement>>& elements, const Recti& scissorBox) const override;
void BuildElement(std::size_t passIndex, const WorldInstance& worldInstance, const SkeletonInstance* skeletonInstance, std::vector<std::unique_ptr<RenderElement>>& elements, const Recti& scissorBox) const override;
inline void Clear();

View File

@@ -16,7 +16,6 @@
namespace Nz
{
class CommandBufferBuilder;
class MaterialSettings;
class RenderBuffer;
class UploadPool;
class WorldInstance;

View File

@@ -40,7 +40,7 @@ namespace Nz
static void OnConstruct(entt::registry& registry, entt::entity entity);
entt::registry& m_registry;
entt::connection m_constructConnection;
entt::scoped_connection m_constructConnection;
PhysWorld2D m_physWorld;
};
}

View File

@@ -40,7 +40,7 @@ namespace Nz
static void OnConstruct(entt::registry& registry, entt::entity entity);
entt::registry& m_registry;
entt::connection m_constructConnection;
entt::scoped_connection m_constructConnection;
PhysWorld3D m_physWorld;
};
}

View File

@@ -30,6 +30,9 @@
#define NAZARA_UTILITY_COMPONENTS_HPP
#include <Nazara/Utility/Components/NodeComponent.hpp>
#include <Nazara/Utility/Components/SharedSkeletonComponent.hpp>
#include <Nazara/Utility/Components/SkeletonComponent.hpp>
#include <Nazara/Utility/Components/SkeletonComponentBase.hpp>
#include <Nazara/Utility/Components/VelocityComponent.hpp>
#endif // NAZARA_UTILITY_COMPONENTS_HPP

View File

@@ -0,0 +1,47 @@
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_UTILITY_COMPONENTS_SHAREDSKELETONCOMPONENT_HPP
#define NAZARA_UTILITY_COMPONENTS_SHAREDSKELETONCOMPONENT_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Utility/Skeleton.hpp>
#include <Nazara/Utility/Components/SkeletonComponentBase.hpp>
namespace Nz
{
class NAZARA_UTILITY_API SharedSkeletonComponent final : public SkeletonComponentBase
{
friend class SkeletonSystem;
public:
SharedSkeletonComponent(std::shared_ptr<Skeleton> skeleton);
SharedSkeletonComponent(const SharedSkeletonComponent& sharedSkeletalComponent);
SharedSkeletonComponent(SharedSkeletonComponent&& sharedSkeletalComponent) noexcept;
~SharedSkeletonComponent() = default;
const Joint& GetAttachedJoint(std::size_t jointIndex) const override;
SharedSkeletonComponent& operator=(const SharedSkeletonComponent& sharedSkeletalComponent);
SharedSkeletonComponent& operator=(SharedSkeletonComponent&& sharedSkeletalComponent) noexcept;
private:
inline bool IsAttachedSkeletonOutdated() const;
void OnReferenceJointsInvalidated(const Skeleton* skeleton);
void SetSkeletonParent(Node* parent);
void SetupSkeleton();
void UpdateAttachedSkeletonJoints();
NazaraSlot(Skeleton, OnSkeletonJointsInvalidated, m_onSkeletonJointsInvalidated);
Skeleton m_attachedSkeleton;
bool m_skeletonJointInvalidated;
};
}
#include <Nazara/Utility/Components/SharedSkeletonComponent.inl>
#endif // NAZARA_UTILITY_COMPONENTS_SHAREDSKELETONCOMPONENT_HPP

View File

@@ -0,0 +1,16 @@
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/Components/SharedSkeletonComponent.hpp>
#include <Nazara/Utility/Debug.hpp>
namespace Nz
{
inline bool SharedSkeletonComponent::IsAttachedSkeletonOutdated() const
{
return m_skeletonJointInvalidated;
}
}
#include <Nazara/Utility/DebugOff.hpp>

View File

@@ -0,0 +1,36 @@
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_UTILITY_COMPONENTS_SKELETONCOMPONENT_HPP
#define NAZARA_UTILITY_COMPONENTS_SKELETONCOMPONENT_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Utility/Skeleton.hpp>
#include <Nazara/Utility/Components/SkeletonComponentBase.hpp>
namespace Nz
{
class Node;
class NAZARA_UTILITY_API SkeletonComponent final : public SkeletonComponentBase
{
public:
SkeletonComponent(std::shared_ptr<Skeleton> skeleton);
SkeletonComponent(const SkeletonComponent&) = delete;
SkeletonComponent(SkeletonComponent&& skeletalComponent) noexcept = default;
~SkeletonComponent() = default;
const Joint& GetAttachedJoint(std::size_t jointIndex) const override;
Node* GetRootNode();
SkeletonComponent& operator=(const SkeletonComponent&) = delete;
SkeletonComponent& operator=(SkeletonComponent&& skeletalComponent) noexcept = default;
};
}
#include <Nazara/Utility/Components/SkeletonComponent.inl>
#endif // NAZARA_UTILITY_COMPONENTS_SKELETONCOMPONENT_HPP

View File

@@ -0,0 +1,12 @@
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/Components/SkeletonComponent.hpp>
#include <Nazara/Utility/Debug.hpp>
namespace Nz
{
}
#include <Nazara/Utility/DebugOff.hpp>

View File

@@ -0,0 +1,38 @@
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_UTILITY_COMPONENTS_SKELETONCOMPONENTBASE_HPP
#define NAZARA_UTILITY_COMPONENTS_SKELETONCOMPONENTBASE_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Utility/Joint.hpp>
#include <Nazara/Utility/Skeleton.hpp>
namespace Nz
{
class NAZARA_UTILITY_API SkeletonComponentBase
{
public:
SkeletonComponentBase(const SkeletonComponentBase&) = default;
SkeletonComponentBase(SkeletonComponentBase&&) noexcept = default;
~SkeletonComponentBase() = default;
virtual const Joint& GetAttachedJoint(std::size_t jointIndex) const = 0;
inline const std::shared_ptr<Skeleton>& GetSkeleton() const;
SkeletonComponentBase& operator=(const SkeletonComponentBase&) = default;
SkeletonComponentBase& operator=(SkeletonComponentBase&&) noexcept = default;
protected:
SkeletonComponentBase(std::shared_ptr<Skeleton> skeleton);
std::shared_ptr<Skeleton> m_referenceSkeleton;
};
}
#include <Nazara/Utility/Components/SkeletonComponentBase.inl>
#endif // NAZARA_UTILITY_COMPONENTS_SKELETONCOMPONENTBASE_HPP

View File

@@ -0,0 +1,21 @@
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/Components/SkeletonComponentBase.hpp>
#include <Nazara/Utility/Debug.hpp>
namespace Nz
{
inline SkeletonComponentBase::SkeletonComponentBase(std::shared_ptr<Skeleton> skeleton) :
m_referenceSkeleton(std::move(skeleton))
{
}
inline const std::shared_ptr<Skeleton>& SkeletonComponentBase::GetSkeleton() const
{
return m_referenceSkeleton;
}
}
#include <Nazara/Utility/DebugOff.hpp>

View File

@@ -29,6 +29,7 @@
#ifndef NAZARA_UTILITY_SYSTEMS_HPP
#define NAZARA_UTILITY_SYSTEMS_HPP
#include <Nazara/Utility/Systems/SkeletonSystem.hpp>
#include <Nazara/Utility/Systems/VelocitySystem.hpp>
#endif // NAZARA_UTILITY_SYSTEMS_HPP

View File

@@ -0,0 +1,41 @@
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_UTILITY_SYSTEMS_SKELETONSYSTEM_HPP
#define NAZARA_UTILITY_SYSTEMS_SKELETONSYSTEM_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Utility/Config.hpp>
#include <entt/entt.hpp>
namespace Nz
{
class NAZARA_UTILITY_API SkeletonSystem
{
public:
static constexpr bool AllowConcurrent = false;
static constexpr Int64 ExecutionOrder = -1'000;
SkeletonSystem(entt::registry& registry);
SkeletonSystem(const SkeletonSystem&) = delete;
SkeletonSystem(SkeletonSystem&&) = delete;
~SkeletonSystem();
void Update(float elapsedTime);
SkeletonSystem& operator=(const SkeletonSystem&) = delete;
SkeletonSystem& operator=(SkeletonSystem&&) = delete;
private:
entt::registry& m_registry;
entt::observer m_sharedSkeletonConstructObserver;
entt::observer m_skeletonConstructObserver;
};
}
#include <Nazara/Utility/Systems/SkeletonSystem.inl>
#endif // NAZARA_UTILITY_SYSTEMS_SKELETONSYSTEM_HPP

View File

@@ -0,0 +1,12 @@
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/Systems/SkeletonSystem.hpp>
#include <Nazara/Utility/Debug.hpp>
namespace Nz
{
}
#include <Nazara/Utility/DebugOff.hpp>