diff --git a/examples/FirstScene/main.cpp b/examples/FirstScene/main.cpp index 62a4425c8..9ed702a69 100644 --- a/examples/FirstScene/main.cpp +++ b/examples/FirstScene/main.cpp @@ -84,7 +84,7 @@ int main() // Ensuite, nous allons rajouter un modèle à notre scène. // Les modèles représentent, globalement, tout ce qui est visible en trois dimensions. // Nous choisirons ici un vaisseau spatial (Quoi de mieux pour une scène spatiale ?) - NzModel spaceship; + NzModel* spaceship = scene.CreateNode(); // Création depuis la scène // Une structure permettant de paramétrer le chargement des modèles NzModelParameters params; @@ -101,7 +101,7 @@ int main() // On charge ensuite le modèle depuis son fichier // Le moteur va charger le fichier et essayer de retrouver les fichiers associés (comme les matériaux, textures, ...) - if (!spaceship.LoadFromFile("resources/Spaceship/spaceship.obj", params)) + if (!spaceship->LoadFromFile("resources/Spaceship/spaceship.obj", params)) { std::cout << "Failed to load spaceship" << std::endl; std::getchar(); @@ -111,7 +111,7 @@ int main() // Nous voulons afficher quelques statistiques relatives au modèle, comme le nombre de sommets et de triangles // Pour cela, nous devons accéder au mesh (maillage 3D) - NzMesh* mesh = spaceship.GetMesh(); + NzMesh* mesh = spaceship->GetMesh(); std::cout << mesh->GetVertexCount() << " sommets" << std::endl; std::cout << mesh->GetTriangleCount() << " triangles" << std::endl; @@ -119,7 +119,7 @@ int main() // En revanche, le format OBJ ne précise pas l'utilisation d'une normal map, nous devons donc la charger manuellement // Pour commencer on récupère le matériau du mesh, celui-ci en possède plusieurs mais celui qui nous intéresse, // celui de la coque, est le second (Cela est bien entendu lié au modèle en lui-même) - NzMaterial* material = spaceship.GetMaterial(1); + NzMaterial* material = spaceship->GetMaterial(1); // On lui indique ensuite le chemin vers la normal map if (!material->SetNormalMap("resources/Spaceship/Texture/normal.png")) @@ -129,10 +129,6 @@ int main() std::cout << "Failed to load normal map" << std::endl; } - // Il nous reste à attacher le modèle à la scène, ce qui se fait simplement via cet appel - spaceship.SetParent(scene); - // Et voilà, à partir de maintenant le modèle fait partie de la hiérarchie de la scène, et sera donc rendu avec cette dernière - // Nous avons besoin également d'une caméra, pour des raisons évidentes, celle-ci sera à l'écart du modèle // regardant dans sa direction. @@ -164,18 +160,15 @@ int main() // -PointLight: Lumière située à un endroit précis, envoyant de la lumière finie dans toutes les directions // -SpotLight: Lumière située à un endroit précis, envoyant de la lumière vers un endroit donné, avec un angle de diffusion - // Nous choisissons une lumière directionnelle représentant la nébuleuse de notre skybox - NzLight nebulaLight(nzLightType_Directional); + // Nous créons une lumière directionnelle pour représenter la nébuleuse de notre skybox + NzLight* nebulaLight = scene.CreateNode(nzLightType_Directional); // Il nous faut ensuite configurer la lumière // Pour commencer, sa couleur, la nébuleuse étant d'une couleur jaune, j'ai choisi ces valeurs - nebulaLight.SetColor(NzColor(255, 182, 90)); + nebulaLight->SetColor(NzColor(255, 182, 90)); // Nous appliquons ensuite une rotation de sorte que la lumière dans la même direction que la nébuleuse - nebulaLight.SetRotation(NzEulerAnglesf(0.f, 102.f, 0.f)); - - // Et nous ajoutons la lumière à la scène - nebulaLight.SetParent(scene); + nebulaLight->SetRotation(NzEulerAnglesf(0.f, 102.f, 0.f)); // Nous allons maintenant créer la fenêtre, dans laquelle nous ferons nos rendus // Celle-ci demande des paramètres plus complexes diff --git a/include/Nazara/Graphics/Camera.hpp b/include/Nazara/Graphics/Camera.hpp index 051db1bdb..8e3622484 100644 --- a/include/Nazara/Graphics/Camera.hpp +++ b/include/Nazara/Graphics/Camera.hpp @@ -9,12 +9,12 @@ #include #include -#include #include #include #include #include #include +#include class NAZARA_API NzCamera : public NzAbstractViewer, public NzNode, NzRenderTarget::Listener { diff --git a/include/Nazara/Graphics/Light.hpp b/include/Nazara/Graphics/Light.hpp index 46655a260..5f24f7e67 100644 --- a/include/Nazara/Graphics/Light.hpp +++ b/include/Nazara/Graphics/Light.hpp @@ -18,17 +18,19 @@ struct NzLightUniforms; class NAZARA_API NzLight : public NzSceneNode { public: - NzLight(nzLightType type); + NzLight(nzLightType type = nzLightType_Point); NzLight(const NzLight& light); ~NzLight() = default; void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const override; + NzLight* Clone() const; + NzLight* Create() const; + void Enable(const NzShader* shader, const NzLightUniforms& uniforms, int offset = 0) const; float GetAmbientFactor() const; float GetAttenuation() const; - const NzBoundingVolumef& GetBoundingVolume() const; NzColor GetColor() const; float GetDiffuseFactor() const; float GetInnerAngle() const; @@ -54,15 +56,13 @@ class NAZARA_API NzLight : public NzSceneNode private: bool FrustumCull(const NzFrustumf& frustum) const override; - void InvalidateNode() override; + void MakeBoundingVolume() const override; void Register() override; void Unregister() override; void UpdateBoundingVolume() const; nzLightType m_type; - mutable NzBoundingVolumef m_boundingVolume; NzColor m_color; - mutable bool m_boundingVolumeUpdated; float m_ambientFactor; float m_attenuation; float m_diffuseFactor; diff --git a/include/Nazara/Graphics/Model.hpp b/include/Nazara/Graphics/Model.hpp index a9f0ac172..129fa28b2 100644 --- a/include/Nazara/Graphics/Model.hpp +++ b/include/Nazara/Graphics/Model.hpp @@ -41,10 +41,12 @@ class NAZARA_API NzModel : public NzSceneNode void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const override; void AdvanceAnimation(float elapsedTime); + NzModel* Clone() const; + NzModel* Create() const; + void EnableAnimation(bool animation); NzAnimation* GetAnimation() const; - const NzBoundingVolumef& GetBoundingVolume() const; NzMaterial* GetMaterial(const NzString& subMeshName) const; NzMaterial* GetMaterial(unsigned int matIndex) const; NzMaterial* GetMaterial(unsigned int skinIndex, const NzString& subMeshName) const; @@ -84,13 +86,10 @@ class NAZARA_API NzModel : public NzSceneNode NzModel& operator=(const NzModel& node); protected: - void InvalidateNode() override; - virtual void UpdateBoundingVolume() const; + void MakeBoundingVolume() const override; std::vector m_materials; - mutable NzBoundingVolumef m_boundingVolume; NzMeshRef m_mesh; - mutable bool m_boundingVolumeUpdated; unsigned int m_matCount; unsigned int m_skin; unsigned int m_skinCount; diff --git a/include/Nazara/Graphics/ParticleSystem.hpp b/include/Nazara/Graphics/ParticleSystem.hpp index f81c42c2e..8484f4628 100644 --- a/include/Nazara/Graphics/ParticleSystem.hpp +++ b/include/Nazara/Graphics/ParticleSystem.hpp @@ -43,7 +43,6 @@ class NAZARA_API NzParticleSystem : public NzSceneNode, NzUpdatable void* GenerateParticle(); void* GenerateParticles(unsigned int count); - const NzBoundingVolumef& GetBoundingVolume() const override; const NzParticleDeclaration* GetDeclaration() const; float GetFixedStepSize() const; unsigned int GetMaxParticleCount() const; @@ -67,22 +66,19 @@ class NAZARA_API NzParticleSystem : public NzSceneNode, NzUpdatable NzParticleSystem& operator=(const NzParticleSystem& emitter); private: - void GenerateAABB() const; + void MakeBoundingVolume() const override; void Register() override; void ResizeBuffer(); void Unregister() override; void Update() override; - void UpdateBoundingVolume() const; std::set> m_dyingParticles; mutable std::vector m_buffer; std::vector m_controllers; std::vector m_emitters; std::vector m_generators; - mutable NzBoundingVolumef m_boundingVolume; NzParticleDeclarationConstRef m_declaration; NzParticleRendererRef m_renderer; - mutable bool m_boundingVolumeUpdated; bool m_fixedStepEnabled; bool m_processing; float m_stepAccumulator; diff --git a/include/Nazara/Graphics/Scene.hpp b/include/Nazara/Graphics/Scene.hpp index 6dbe5250e..04febb346 100644 --- a/include/Nazara/Graphics/Scene.hpp +++ b/include/Nazara/Graphics/Scene.hpp @@ -8,37 +8,49 @@ #define NAZARA_SCENE_HPP #include +#include #include +#include #include #include #include +#include #include +#include +#include +#include class NzAbstractRenderQueue; class NzAbstractViewer; -class NzCamera; -class NzLight; -class NzModel; class NzNode; -class NzRenderQueue; class NzSceneNode; -struct NzSceneImpl; class NAZARA_API NzScene { - friend NzCamera; + friend NzSceneNode; public: NzScene(); - ~NzScene(); + ~NzScene() = default; void AddToVisibilityList(NzUpdatable* object); + template T* CreateNode(Args&&... args); + template T* CreateNode(const NzString& name, Args&&... args); + template T* CreateNode(const NzString& name, const NzString& templateNodeName); + + void Clear(); + void Cull(); void Draw(); void EnableBackground(bool enable); + NzSceneNode* FindNode(const NzString& name); + const NzSceneNode* FindNode(const NzString& name) const; + template T* FindNodeAs(const NzString& name); + template const T* FindNodeAs(const NzString& name) const; + NzColor GetAmbientColor() const; NzAbstractBackground* GetBackground() const; NzVector3f GetBackward() const; @@ -47,7 +59,8 @@ class NAZARA_API NzScene NzVector3f GetLeft() const; NzAbstractRenderTechnique* GetRenderTechnique() const; NzVector3f GetRight() const; - NzSceneNode& GetRoot() const; + NzSceneNode& GetRoot(); + const NzSceneNode& GetRoot() const; NzAbstractViewer* GetViewer() const; NzVector3f GetUp() const; float GetUpdateTime() const; @@ -57,6 +70,11 @@ class NAZARA_API NzScene void RegisterForUpdate(NzUpdatable* object); + void RemoveNode(NzSceneNode* node); + void RemoveNode(const NzString& name); + + void RenderFrame(); + void SetAmbientColor(const NzColor& color); void SetBackground(NzAbstractBackground* background); void SetRenderTechnique(NzAbstractRenderTechnique* renderTechnique); @@ -72,9 +90,28 @@ class NAZARA_API NzScene operator const NzSceneNode&() const; private: + bool ChangeNodeName(NzSceneNode* node, const NzString& newName); + bool RegisterSceneNode(const NzString& name, NzSceneNode* node); void RecursiveFrustumCull(NzAbstractRenderQueue* renderQueue, const NzFrustumf& frustum, NzNode* node); - NzSceneImpl* m_impl; + mutable std::unique_ptr m_background; + mutable std::unique_ptr m_renderTechnique; + std::unordered_map m_nodeMap; + std::vector> m_nodes; + std::vector m_updateList; + std::vector m_visibleUpdateList; + NzClock m_updateClock; + NzColor m_ambientColor; + NzSceneRoot m_root; + NzAbstractViewer* m_viewer; + bool m_backgroundEnabled; + bool m_update; + float m_frameTime; + float m_updateTime; + mutable int m_renderTechniqueRanking; + unsigned int m_updatePerSecond; }; +#include + #endif // NAZARA_SCENE_HPP diff --git a/include/Nazara/Graphics/Scene.inl b/include/Nazara/Graphics/Scene.inl new file mode 100644 index 000000000..2231d1364 --- /dev/null +++ b/include/Nazara/Graphics/Scene.inl @@ -0,0 +1,139 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +///TODO: Déplacer vers SceneNode et exposer + +// Pour être sûr que ce code soit à jour +static_assert(nzSceneNodeType_Max == 6, "Please update the code below"); + +class NzLight; +class NzModel; +class NzParticleEmitter; +class NzSceneRoot; +class NzSprite; +class NzTextSprite; + +template +constexpr nzSceneNodeType NzImplGetType() +{ + return nzSceneNodeType_User; +} + +template<> +inline constexpr nzSceneNodeType NzImplGetType() +{ + return nzSceneNodeType_Light; +} + +template<> +inline constexpr nzSceneNodeType NzImplGetType() +{ + return nzSceneNodeType_Model; +} + +template<> +inline constexpr nzSceneNodeType NzImplGetType() +{ + return nzSceneNodeType_ParticleEmitter; +} + +template<> +inline constexpr nzSceneNodeType NzImplGetType() +{ + return nzSceneNodeType_Root; +} + +template<> +inline constexpr nzSceneNodeType NzImplGetType() +{ + return nzSceneNodeType_Sprite; +} + +template<> +inline constexpr nzSceneNodeType NzImplGetType() +{ + return nzSceneNodeType_TextSprite; +} + + +template +T* NzScene::CreateNode(Args&&... args) +{ + std::unique_ptr node(new T(std::forward(args)...)); + if (!RegisterSceneNode(NzString(), node.get())) + return nullptr; + + return node.release(); +} + +template +T* NzScene::CreateNode(const NzString& name, Args&&... args) +{ + std::unique_ptr node(new T(std::forward(args)...)); + if (!RegisterSceneNode(name, node.get())) + return nullptr; + + return node.release(); +} + +template +T* NzScene::CreateNode(const NzString& name, const NzString& templateNodeName) +{ + auto it = m_nodeMap.find(templateNodeName); + if (it == m_nodeMap.end()) + { + NazaraError("Node \"" + templateNodeName + "\" is not registred"); + return nullptr; + } + + NzSceneNode* sceneNode = it->second; + if (sceneNode->GetSceneNodeType() != NzImplGetType()) + { + NazaraError("Scene node type of T (" + NzString::Number(NzImplGetType()) + ") doesn't match template scene node type (" + NzString::Number(sceneNode->GetSceneNodeType()) + ")"); + return nullptr; + } + + std::unique_ptr node(static_cast(sceneNode)->Copy()); + if (!RegisterSceneNode(name, node.get())) + return nullptr; + + return node.release(); +} + +template +T* NzScene::FindNodeAs(const NzString& name) +{ + NzSceneNode* sceneNode = FindNode(name); + if (!sceneNode) + return nullptr; + + if (sceneNode->GetSceneNodeType() != NzImplGetType()) + { + NazaraError("Scene node type of T (" + NzString::Number(NzImplGetType()) + ") doesn't match \"" + name + "\" scene node type (" + NzString::Number(sceneNode->GetSceneNodeType()) + ")"); + return nullptr; + } + + return static_cast(sceneNode); +} + +template +const T* NzScene::FindNodeAs(const NzString& name) const +{ + const NzSceneNode* sceneNode = FindNode(name); + if (!sceneNode) + return nullptr; + + if (sceneNode->GetSceneNodeType() != NzImplGetType()) + { + NazaraError("Scene node type of T (" + NzString::Number(NzImplGetType()) + ") doesn't match \"" + name + "\" scene node type (" + NzString::Number(sceneNode->GetSceneNodeType()) + ")"); + return nullptr; + } + + return static_cast(sceneNode); +} + +#include diff --git a/include/Nazara/Graphics/SceneNode.hpp b/include/Nazara/Graphics/SceneNode.hpp index 47a977c8a..dea994277 100644 --- a/include/Nazara/Graphics/SceneNode.hpp +++ b/include/Nazara/Graphics/SceneNode.hpp @@ -9,14 +9,16 @@ #include #include -#include #include #include #include +class NzAbstractRenderQueue; +class NzScene; + class NAZARA_API NzSceneNode : public NzNode { - friend class NzScene; + friend NzScene; public: NzSceneNode(); @@ -26,42 +28,59 @@ class NAZARA_API NzSceneNode : public NzNode virtual void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const = 0; + // Idiôme "virtual constructor" + virtual NzSceneNode* Clone() const = 0; + virtual NzSceneNode* Create() const = 0; + void EnableDrawing(bool drawingEnabled); NzVector3f GetBackward() const; - virtual const NzBoundingVolumef& GetBoundingVolume() const = 0; + virtual const NzBoundingVolumef& GetBoundingVolume() const; NzVector3f GetDown() const; NzVector3f GetForward() const; NzVector3f GetLeft() const; + const NzString& GetName() const; nzNodeType GetNodeType() const final; NzVector3f GetRight() const; NzScene* GetScene() const; virtual nzSceneNodeType GetSceneNodeType() const = 0; NzVector3f GetUp() const; + void InvalidateAABB(); + virtual bool IsDrawable() const = 0; bool IsDrawingEnabled() const; bool IsVisible() const; + bool SetName(const NzString& name); + NzSceneNode& operator=(const NzSceneNode& sceneNode); NzSceneNode& operator=(NzSceneNode&& sceneNode) = delete; protected: virtual bool FrustumCull(const NzFrustumf& frustum) const; + virtual void InvalidateNode() override; + virtual void MakeBoundingVolume() const = 0; virtual void OnParenting(const NzNode* parent) override; virtual void OnVisibilityChange(bool visibility); void RecursiveSetScene(NzScene* scene, NzNode* node); virtual void Register(); + void SetNameInternal(const NzString& name); void SetScene(NzScene* scene); virtual void Unregister(); virtual void Update(); + virtual void UpdateBoundingVolume() const; + mutable NzBoundingVolumef m_boundingVolume; NzScene* m_scene; + mutable bool m_boundingVolumeUpdated; bool m_drawingEnabled; bool m_visible; private: void UpdateVisibility(const NzFrustumf& frustum); + + NzString m_name; }; #endif // NAZARA_SCENENODE_HPP diff --git a/include/Nazara/Graphics/SceneRoot.hpp b/include/Nazara/Graphics/SceneRoot.hpp index 41935cf94..60ae329be 100644 --- a/include/Nazara/Graphics/SceneRoot.hpp +++ b/include/Nazara/Graphics/SceneRoot.hpp @@ -10,14 +10,15 @@ #include #include +class NzScene; + class NAZARA_API NzSceneRoot : public NzSceneNode { - friend struct NzSceneImpl; + friend NzScene; public: void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const override; - const NzBoundingVolumef& GetBoundingVolume() const override; nzSceneNodeType GetSceneNodeType() const override; bool IsDrawable() const; @@ -26,6 +27,10 @@ class NAZARA_API NzSceneRoot : public NzSceneNode NzSceneRoot(NzScene* scene); virtual ~NzSceneRoot(); + NzSceneRoot* Clone() const; + NzSceneRoot* Create() const; + + void MakeBoundingVolume() const override; void Register(); void Unregister(); }; diff --git a/include/Nazara/Graphics/SkeletalModel.hpp b/include/Nazara/Graphics/SkeletalModel.hpp index 82b0c69a9..e29fc4d79 100644 --- a/include/Nazara/Graphics/SkeletalModel.hpp +++ b/include/Nazara/Graphics/SkeletalModel.hpp @@ -31,7 +31,6 @@ using NzSkeletalModelLoader = NzResourceLoader m_renderInfos; mutable std::vector m_localVertices; mutable std::vector m_vertices; - mutable NzBoundingVolumef m_boundingVolume; NzColor m_color; NzMaterialRef m_material; NzRectui m_localBounds; - mutable bool m_boundingVolumeUpdated; mutable bool m_verticesUpdated; }; diff --git a/include/Nazara/Graphics/View.hpp b/include/Nazara/Graphics/View.hpp index 1c3f073e5..41cab8fe8 100644 --- a/include/Nazara/Graphics/View.hpp +++ b/include/Nazara/Graphics/View.hpp @@ -9,12 +9,12 @@ #include #include -#include #include #include #include #include #include +#include class NAZARA_API NzView : public NzAbstractViewer, public NzNode, NzRenderTarget::Listener { diff --git a/include/Nazara/Utility/Node.hpp b/include/Nazara/Utility/Node.hpp index f7d33286b..7f9662d33 100644 --- a/include/Nazara/Utility/Node.hpp +++ b/include/Nazara/Utility/Node.hpp @@ -35,7 +35,6 @@ class NAZARA_API NzNode NzQuaternionf GetInitialRotation() const; NzVector3f GetInitialScale() const; virtual NzVector3f GetLeft() const; - const NzString& GetName() const; virtual nzNodeType GetNodeType() const; const NzNode* GetParent() const; NzVector3f GetPosition(nzCoordSys coordSys = nzCoordSys_Global) const; @@ -67,7 +66,6 @@ class NAZARA_API NzNode void SetInitialScale(float scaleX, float scaleY, float scaleZ = 1.f); void SetInitialPosition(const NzVector3f& translation); void SetInitialPosition(float translationX, float translationXY, float translationZ = 0.f); - void SetName(const NzString& name); void SetParent(const NzNode* node = nullptr, bool keepDerived = false); void SetParent(const NzNode& node, bool keepDerived = false); void SetPosition(const NzVector3f& translation, nzCoordSys coordSys = nzCoordSys_Local); @@ -103,7 +101,6 @@ class NAZARA_API NzNode mutable NzQuaternionf m_derivedRotation; NzQuaternionf m_initialRotation; NzQuaternionf m_rotation; - NzString m_name; mutable NzVector3f m_derivedPosition; mutable NzVector3f m_derivedScale; NzVector3f m_initialPosition; diff --git a/src/Nazara/Graphics/DeferredRenderTechnique.cpp b/src/Nazara/Graphics/DeferredRenderTechnique.cpp index fb2d6320f..2b9a30aa6 100644 --- a/src/Nazara/Graphics/DeferredRenderTechnique.cpp +++ b/src/Nazara/Graphics/DeferredRenderTechnique.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include diff --git a/src/Nazara/Graphics/ForwardRenderTechnique.cpp b/src/Nazara/Graphics/ForwardRenderTechnique.cpp index 2144d5803..534ecf449 100644 --- a/src/Nazara/Graphics/ForwardRenderTechnique.cpp +++ b/src/Nazara/Graphics/ForwardRenderTechnique.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include diff --git a/src/Nazara/Graphics/Light.cpp b/src/Nazara/Graphics/Light.cpp index 17b726f35..414c6cffa 100644 --- a/src/Nazara/Graphics/Light.cpp +++ b/src/Nazara/Graphics/Light.cpp @@ -14,11 +14,11 @@ #include ///TODO: Utilisation des UBOs +///TODO: Scale ? NzLight::NzLight(nzLightType type) : m_type(type), m_color(NzColor::White), -m_boundingVolumeUpdated(false), m_ambientFactor((type == nzLightType_Directional) ? 0.2f : 0.f), m_attenuation(0.9f), m_diffuseFactor(1.f), @@ -31,9 +31,7 @@ m_radius(5.f) NzLight::NzLight(const NzLight& light) : NzSceneNode(light), m_type(light.m_type), -m_boundingVolume(light.m_boundingVolume), m_color(light.m_color), -m_boundingVolumeUpdated(light.m_boundingVolumeUpdated), m_ambientFactor(light.m_ambientFactor), m_attenuation(light.m_attenuation), m_diffuseFactor(light.m_diffuseFactor), @@ -49,6 +47,16 @@ void NzLight::AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const renderQueue->AddLight(this); } +NzLight* NzLight::Clone() const +{ + return new NzLight(*this); +} + +NzLight* NzLight::Create() const +{ + return new NzLight; +} + void NzLight::Enable(const NzShader* shader, const NzLightUniforms& uniforms, int offset) const { /* @@ -112,14 +120,6 @@ float NzLight::GetAttenuation() const return m_attenuation; } -const NzBoundingVolumef& NzLight::GetBoundingVolume() const -{ - if (!m_boundingVolumeUpdated) - UpdateBoundingVolume(); - - return m_boundingVolume; -} - NzColor NzLight::GetColor() const { return m_color; @@ -251,11 +251,45 @@ bool NzLight::FrustumCull(const NzFrustumf& frustum) const return false; } -void NzLight::InvalidateNode() +void NzLight::MakeBoundingVolume() const { - NzSceneNode::InvalidateNode(); + switch (m_type) + { + case nzLightType_Directional: + m_boundingVolume.MakeInfinite(); + break; - m_boundingVolumeUpdated = false; + case nzLightType_Point: + { + NzVector3f radius(m_radius); + m_boundingVolume.Set(-radius, radius); + break; + } + + case nzLightType_Spot: + { + // On forme une boite sur l'origine + NzBoxf box(NzVector3f::Zero()); + + // On calcule le reste des points + NzVector3f base(NzVector3f::Forward()*m_radius); + + // Il nous faut maintenant le rayon du cercle projeté à cette distance + // Tangente = Opposé/Adjaçent <=> Opposé = Adjaçent*Tangente + float radius = m_radius*std::tan(NzDegreeToRadian(m_outerAngle)); + NzVector3f lExtend = NzVector3f::Left()*radius; + NzVector3f uExtend = NzVector3f::Up()*radius; + + // Et on ajoute ensuite les quatres extrémités de la pyramide + box.ExtendTo(base + lExtend + uExtend); + box.ExtendTo(base + lExtend - uExtend); + box.ExtendTo(base - lExtend + uExtend); + box.ExtendTo(base - lExtend - uExtend); + + m_boundingVolume.Set(box); + break; + } + } } void NzLight::Register() @@ -269,46 +303,7 @@ void NzLight::Unregister() void NzLight::UpdateBoundingVolume() const { if (m_boundingVolume.IsNull()) - { - switch (m_type) - { - case nzLightType_Directional: - m_boundingVolume.MakeInfinite(); - m_boundingVolumeUpdated = true; - return; // Rien d'autre à faire - - case nzLightType_Point: - { - NzVector3f radius(m_radius); - m_boundingVolume.Set(-radius, radius); - break; - } - - case nzLightType_Spot: - { - // On forme une boite sur l'origine - NzBoxf box(NzVector3f::Zero()); - - // On calcule le reste des points - NzVector3f base(NzVector3f::Forward()*m_radius); - - // Il nous faut maintenant le rayon du cercle projeté à cette distance - // Tangente = Opposé/Adjaçent <=> Opposé = Adjaçent*Tangente - float radius = m_radius*std::tan(NzDegreeToRadian(m_outerAngle)); - NzVector3f lExtend = NzVector3f::Left()*radius; - NzVector3f uExtend = NzVector3f::Up()*radius; - - // Et on ajoute ensuite les quatres extrémités de la pyramide - box.ExtendTo(base + lExtend + uExtend); - box.ExtendTo(base + lExtend - uExtend); - box.ExtendTo(base - lExtend + uExtend); - box.ExtendTo(base - lExtend - uExtend); - - m_boundingVolume.Set(box); - break; - } - } - } + MakeBoundingVolume(); switch (m_type) { diff --git a/src/Nazara/Graphics/Model.cpp b/src/Nazara/Graphics/Model.cpp index 1a19a1b8a..425e19cfb 100644 --- a/src/Nazara/Graphics/Model.cpp +++ b/src/Nazara/Graphics/Model.cpp @@ -25,7 +25,6 @@ bool NzModelParameters::IsValid() const } NzModel::NzModel() : -m_boundingVolumeUpdated(true), m_matCount(0), m_skin(0), m_skinCount(1) @@ -35,9 +34,7 @@ m_skinCount(1) NzModel::NzModel(const NzModel& model) : NzSceneNode(model), m_materials(model.m_materials), -m_boundingVolume(model.m_boundingVolume), m_mesh(model.m_mesh), -m_boundingVolumeUpdated(model.m_boundingVolumeUpdated), m_matCount(model.m_matCount), m_skin(model.m_skin), m_skinCount(model.m_skinCount) @@ -69,22 +66,14 @@ void NzModel::AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const } } -const NzBoundingVolumef& NzModel::GetBoundingVolume() const +NzModel* NzModel::Clone() const { - #if NAZARA_GRAPHICS_SAFE - if (!m_mesh) - { - NazaraError("Model has no mesh"); + return new NzModel(*this); +} - static NzBoundingVolumef dummy(nzExtend_Null); - return dummy; - } - #endif - - if (!m_boundingVolumeUpdated) - UpdateBoundingVolume(); - - return m_boundingVolume; +NzModel* NzModel::Create() const +{ + return new NzModel; } NzMaterial* NzModel::GetMaterial(const NzString& subMeshName) const @@ -414,23 +403,12 @@ NzModel& NzModel::operator=(const NzModel& node) return *this; } -void NzModel::InvalidateNode() +void NzModel::MakeBoundingVolume() const { - NzSceneNode::InvalidateNode(); - - m_boundingVolumeUpdated = false; -} - -void NzModel::UpdateBoundingVolume() const -{ - if (m_boundingVolume.IsNull()) + if (m_mesh) m_boundingVolume.Set(m_mesh->GetAABB()); - - if (!m_transformMatrixUpdated) - UpdateTransformMatrix(); - - m_boundingVolume.Update(m_transformMatrix); - m_boundingVolumeUpdated = true; + else + m_boundingVolume.MakeNull(); } NzModelLoader::LoaderList NzModel::s_loaders; diff --git a/src/Nazara/Graphics/ParticleSystem.cpp b/src/Nazara/Graphics/ParticleSystem.cpp index 43e1cac9f..3a7351b2c 100644 --- a/src/Nazara/Graphics/ParticleSystem.cpp +++ b/src/Nazara/Graphics/ParticleSystem.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -18,7 +19,6 @@ NzParticleSystem(maxParticleCount, NzParticleDeclaration::Get(layout)) NzParticleSystem::NzParticleSystem(unsigned int maxParticleCount, const NzParticleDeclaration* declaration) : m_declaration(declaration), -m_boundingVolumeUpdated(false), m_fixedStepEnabled(false), m_processing(false), m_stepAccumulator(0.f), @@ -38,10 +38,8 @@ NzParticleSystem::NzParticleSystem(const NzParticleSystem& system) : NzSceneNode(system), m_controllers(system.m_controllers), m_generators(system.m_generators), -m_boundingVolume(system.m_boundingVolume), m_declaration(system.m_declaration), m_renderer(system.m_renderer), -m_boundingVolumeUpdated(system.m_boundingVolumeUpdated), m_fixedStepEnabled(system.m_fixedStepEnabled), m_processing(false), m_stepAccumulator(0.f), @@ -132,14 +130,6 @@ void* NzParticleSystem::GenerateParticles(unsigned int count) return ptr; } -const NzBoundingVolumef& NzParticleSystem::GetBoundingVolume() const -{ - if (!m_boundingVolumeUpdated) - UpdateBoundingVolume(); - - return m_boundingVolume; -} - const NzParticleDeclaration* NzParticleSystem::GetDeclaration() const { return m_declaration; @@ -238,8 +228,6 @@ NzParticleSystem& NzParticleSystem::operator=(const NzParticleSystem& system) NzSceneNode::operator=(system); - m_boundingVolume = system.m_boundingVolume; - m_boundingVolumeUpdated = system.m_boundingVolumeUpdated; m_controllers = system.m_controllers; m_declaration = system.m_declaration; m_fixedStepEnabled = system.m_fixedStepEnabled; @@ -308,7 +296,7 @@ void NzParticleSystem::ApplyControllers(NzParticleMapper& mapper, unsigned int p m_dyingParticles.clear(); } -void NzParticleSystem::GenerateAABB() const +void NzParticleSystem::MakeBoundingVolume() const { ///TODO: Calculer l'AABB (prendre la taille des particules en compte s'il y a) m_boundingVolume.MakeInfinite(); @@ -356,16 +344,3 @@ void NzParticleSystem::Update() ApplyControllers(mapper, m_particleCount, elapsedTime, m_stepAccumulator); } } - -void NzParticleSystem::UpdateBoundingVolume() const -{ - if (m_boundingVolume.IsNull()) - GenerateAABB(); - - if (!m_transformMatrixUpdated) - UpdateTransformMatrix(); - - ///FIXME: Pourquoi est-ce que le particle system est un node ? Il serait trop coûteux de calculer les particules relativement - m_boundingVolume.Update(m_transformMatrix); - m_boundingVolumeUpdated = true; -} diff --git a/src/Nazara/Graphics/Scene.cpp b/src/Nazara/Graphics/Scene.cpp index d0115b8b0..289ff1b1e 100644 --- a/src/Nazara/Graphics/Scene.cpp +++ b/src/Nazara/Graphics/Scene.cpp @@ -9,57 +9,36 @@ #include #include #include -#include #include #include #include -#include -#include -#include #include -struct NzSceneImpl +NzScene::NzScene() : +m_ambientColor(25, 25, 25), +m_root(this), +m_viewer(nullptr), +m_backgroundEnabled(true), +m_update(false), +m_updatePerSecond(60) { - NzSceneImpl(NzScene* scene) : - root(scene) - { - } - - std::unique_ptr background; - std::unique_ptr renderTechnique; - std::vector updateList; - std::vector visibleUpdateList; - NzClock updateClock; - NzColor ambientColor = NzColor(25,25,25); - NzSceneRoot root; - NzAbstractViewer* viewer = nullptr; - bool backgroundEnabled = true; - bool update = false; - float frameTime; - float updateTime; - int renderTechniqueRanking; - unsigned int updatePerSecond = 60; -}; - -NzScene::NzScene() -{ - m_impl = new NzSceneImpl(this); -} - -NzScene::~NzScene() -{ - delete m_impl; } void NzScene::AddToVisibilityList(NzUpdatable* object) { - m_impl->visibleUpdateList.push_back(object); + m_visibleUpdateList.push_back(object); +} + +void NzScene::Clear() +{ + m_nodeMap.clear(); + m_nodes.clear(); } void NzScene::Cull() { #if NAZARA_GRAPHICS_SAFE - if (!m_impl->viewer) + if (!m_viewer) { NazaraError("No viewer"); return; @@ -69,42 +48,40 @@ void NzScene::Cull() NzAbstractRenderQueue* renderQueue = GetRenderTechnique()->GetRenderQueue(); renderQueue->Clear(false); - m_impl->visibleUpdateList.clear(); + m_visibleUpdateList.clear(); // Frustum culling - RecursiveFrustumCull(renderQueue, m_impl->viewer->GetFrustum(), &m_impl->root); + RecursiveFrustumCull(renderQueue, m_viewer->GetFrustum(), &m_root); ///TODO: Occlusion culling - - ///TODO: Light culling } void NzScene::Draw() { #if NAZARA_GRAPHICS_SAFE - if (!m_impl->viewer) + if (!m_viewer) { NazaraError("No viewer"); return; } #endif - m_impl->viewer->ApplyView(); + m_viewer->ApplyView(); try { - NzErrorFlags errFlags(nzErrorFlag_ThrowException); - m_impl->renderTechnique->Clear(this); - m_impl->renderTechnique->Draw(this); + NzErrorFlags errFlags(nzErrorFlag_ThrowException, true); + m_renderTechnique->Clear(this); + m_renderTechnique->Draw(this); } catch (const std::exception& e) { - NzString oldName = m_impl->renderTechnique->GetName(); + NzString oldName = m_renderTechnique->GetName(); - if (m_impl->renderTechniqueRanking > 0) + if (m_renderTechniqueRanking > 0) { - m_impl->renderTechnique.reset(NzRenderTechniques::GetByRanking(m_impl->renderTechniqueRanking-1, &m_impl->renderTechniqueRanking)); - NazaraError("Render technique \"" + oldName + "\" failed, fallback to \"" + m_impl->renderTechnique->GetName() + '"'); + m_renderTechnique.reset(NzRenderTechniques::GetByRanking(m_renderTechniqueRanking-1, &m_renderTechniqueRanking)); + NazaraError("Render technique \"" + oldName + "\" failed, falling back to \"" + m_renderTechnique->GetName() + '"'); } else { @@ -118,131 +95,154 @@ void NzScene::Draw() void NzScene::EnableBackground(bool enable) { - m_impl->backgroundEnabled = enable; + m_backgroundEnabled = enable; +} + +NzSceneNode* NzScene::FindNode(const NzString& name) +{ + auto it = m_nodeMap.find(name); + if (it == m_nodeMap.end()) + return nullptr; + + return it->second; +} + +const NzSceneNode* NzScene::FindNode(const NzString& name) const +{ + auto it = m_nodeMap.find(name); + if (it == m_nodeMap.end()) + return nullptr; + + return it->second; } NzColor NzScene::GetAmbientColor() const { - return m_impl->ambientColor; + return m_ambientColor; } NzAbstractBackground* NzScene::GetBackground() const { - if (!m_impl->background) - m_impl->background.reset(new NzColorBackground); + if (!m_background) + m_background.reset(new NzColorBackground); - return m_impl->background.get(); + return m_background.get(); } NzVector3f NzScene::GetBackward() const { #if NAZARA_GRAPHICS_SAFE - if (!m_impl->viewer) + if (!m_viewer) { NazaraError("No viewer"); return NzVector3f::Backward(); } #endif - return -m_impl->viewer->GetGlobalForward(); + return -m_viewer->GetGlobalForward(); } NzVector3f NzScene::GetDown() const { #if NAZARA_GRAPHICS_SAFE - if (!m_impl->viewer) + if (!m_viewer) { NazaraError("No viewer"); return NzVector3f::Down(); } #endif - return -m_impl->viewer->GetGlobalUp(); + return -m_viewer->GetGlobalUp(); } NzVector3f NzScene::GetForward() const { #if NAZARA_GRAPHICS_SAFE - if (!m_impl->viewer) + if (!m_viewer) { NazaraError("No viewer"); return NzVector3f::Forward(); } #endif - return m_impl->viewer->GetGlobalForward(); + return m_viewer->GetGlobalForward(); } NzVector3f NzScene::GetLeft() const { #if NAZARA_GRAPHICS_SAFE - if (!m_impl->viewer) + if (!m_viewer) { NazaraError("No viewer"); return NzVector3f::Left(); } #endif - return -m_impl->viewer->GetGlobalRight(); + return -m_viewer->GetGlobalRight(); } NzAbstractRenderTechnique* NzScene::GetRenderTechnique() const { - if (!m_impl->renderTechnique) - m_impl->renderTechnique.reset(NzRenderTechniques::GetByRanking(-1, &m_impl->renderTechniqueRanking)); + if (!m_renderTechnique) + m_renderTechnique.reset(NzRenderTechniques::GetByRanking(-1, &m_renderTechniqueRanking)); - return m_impl->renderTechnique.get(); + return m_renderTechnique.get(); } NzVector3f NzScene::GetRight() const { #if NAZARA_GRAPHICS_SAFE - if (!m_impl->viewer) + if (!m_viewer) { NazaraError("No viewer"); return NzVector3f::Right(); } #endif - return m_impl->viewer->GetGlobalRight(); + return m_viewer->GetGlobalRight(); } -NzSceneNode& NzScene::GetRoot() const +NzSceneNode& NzScene::GetRoot() { - return m_impl->root; + return m_root; +} + +const NzSceneNode& NzScene::GetRoot() const +{ + return m_root; } NzAbstractViewer* NzScene::GetViewer() const { - return m_impl->viewer; + return m_viewer; } NzVector3f NzScene::GetUp() const { #if NAZARA_GRAPHICS_SAFE - if (!m_impl->viewer) + if (!m_viewer) { NazaraError("No viewer"); return NzVector3f::Up(); } #endif - return m_impl->viewer->GetGlobalUp(); + return m_viewer->GetGlobalUp(); } float NzScene::GetUpdateTime() const { - return m_impl->updateTime; + return m_updateTime; } unsigned int NzScene::GetUpdatePerSecond() const { - return m_impl->updatePerSecond; + return m_updatePerSecond; } bool NzScene::IsBackgroundEnabled() const { - return m_impl->backgroundEnabled; + return m_backgroundEnabled; } void NzScene::RegisterForUpdate(NzUpdatable* object) @@ -255,32 +255,76 @@ void NzScene::RegisterForUpdate(NzUpdatable* object) } #endif - m_impl->updateList.push_back(object); + m_updateList.push_back(object); +} + +void NzScene::RemoveNode(NzSceneNode* node) +{ + if (!node) + return; + + // C'est moche mais je n'ai pas d'autre choix que d'utiliser un std::unique_ptr pour utiliser std::find + std::unique_ptr ptr(node); + auto it = std::find(m_nodes.begin(), m_nodes.end(), ptr); + ptr.release(); + + if (it == m_nodes.end()) + { + NazaraError("This scene node doesn't belong to this scene"); + return; + } + + NzString nodeName = node->GetName(); + if (!nodeName.IsEmpty()) + m_nodeMap.erase(nodeName); + + m_nodes.erase(it); +} + +void NzScene::RemoveNode(const NzString& name) +{ + RemoveNode(FindNode(name)); +} + +void NzScene::RenderFrame() +{ + try + { + NzErrorFlags errFlags(nzErrorFlag_ThrowException, true); + Update(); + Cull(); + UpdateVisible(); + Draw(); + } + catch (const std::exception& e) + { + NazaraError("Failed to render frame: " + NzString(e.what())); + } } void NzScene::SetAmbientColor(const NzColor& color) { - m_impl->ambientColor = color; + m_ambientColor = color; } void NzScene::SetBackground(NzAbstractBackground* background) { - m_impl->background.reset(background); + m_background.reset(background); } void NzScene::SetRenderTechnique(NzAbstractRenderTechnique* renderTechnique) { - m_impl->renderTechnique.reset(renderTechnique); + m_renderTechnique.reset(renderTechnique); } void NzScene::SetViewer(NzAbstractViewer* viewer) { - if (m_impl->viewer != viewer) + if (m_viewer != viewer) { - m_impl->viewer = viewer; + m_viewer = viewer; // Invalidation de tous les nodes de la scène (utile pour la régénération des sommets dépendant du viewer) - m_impl->root.InvalidateNode(); + m_root.InvalidateNode(); } } @@ -291,7 +335,7 @@ void NzScene::SetViewer(NzAbstractViewer& viewer) void NzScene::SetUpdatePerSecond(unsigned int updatePerSecond) { - m_impl->updatePerSecond = updatePerSecond; + m_updatePerSecond = updatePerSecond; } void NzScene::UnregisterForUpdate(NzUpdatable* object) @@ -304,20 +348,20 @@ void NzScene::UnregisterForUpdate(NzUpdatable* object) } #endif - auto it = std::find(m_impl->updateList.begin(), m_impl->updateList.end(), object); - if (it != m_impl->updateList.end()) - m_impl->updateList.erase(it); + auto it = std::find(m_updateList.begin(), m_updateList.end(), object); + if (it != m_updateList.end()) + m_updateList.erase(it); } void NzScene::Update() { - m_impl->update = (m_impl->updatePerSecond == 0 || m_impl->updateClock.GetMilliseconds() > 1000/m_impl->updatePerSecond); - if (m_impl->update) + m_update = (m_updatePerSecond == 0 || m_updateClock.GetMilliseconds() > 1000/m_updatePerSecond); + if (m_update) { - m_impl->updateTime = m_impl->updateClock.GetSeconds(); - m_impl->updateClock.Restart(); + m_updateTime = m_updateClock.GetSeconds(); + m_updateClock.Restart(); - for (NzUpdatable* updatable : m_impl->updateList) + for (NzUpdatable* updatable : m_updateList) ///TODO: Multihreading updatable->Update(); } @@ -327,16 +371,68 @@ void NzScene::UpdateVisible() { NzSkinningManager::Skin(); - if (m_impl->update) + if (m_update) { - for (NzUpdatable* node : m_impl->visibleUpdateList) + for (NzUpdatable* node : m_visibleUpdateList) node->Update(); } } NzScene::operator const NzSceneNode&() const { - return m_impl->root; + return m_root; +} + +bool NzScene::ChangeNodeName(NzSceneNode* node, const NzString& newName) +{ + #ifdef NAZARA_DEBUG + std::unique_ptr ptr(node); + auto it = std::find(m_nodes.begin(), m_nodes.end(), ptr); + ptr.release(); + + if (it == m_nodes.end()) + { + NazaraInternalError("Node isn't part of the scene"); + return false; + } + #endif + + if (!newName.IsEmpty()) + { + auto pair = m_nodeMap.insert(std::make_pair(newName, node)); + if (!pair.second) + { + NazaraError("Name \"" + newName + "\" is already in use"); + return false; + } + } + + NzString oldName = node->GetName(); + if (!oldName.IsEmpty()) + m_nodeMap.erase(oldName); + + node->SetNameInternal(newName); + return true; +} + +bool NzScene::RegisterSceneNode(const NzString& name, NzSceneNode* node) +{ + if (!name.IsEmpty()) + { + if (m_nodeMap.find(name) != m_nodeMap.end()) + { + NazaraError("Node " + name + " is already registred"); + return false; + } + + m_nodeMap[name] = node; + } + + node->SetNameInternal(name); + node->SetParent(m_root, true); + + m_nodes.emplace_back(node); + return true; } void NzScene::RecursiveFrustumCull(NzAbstractRenderQueue* renderQueue, const NzFrustumf& frustum, NzNode* node) diff --git a/src/Nazara/Graphics/SceneNode.cpp b/src/Nazara/Graphics/SceneNode.cpp index b0e42bc1d..1c7062e30 100644 --- a/src/Nazara/Graphics/SceneNode.cpp +++ b/src/Nazara/Graphics/SceneNode.cpp @@ -11,6 +11,7 @@ NzSceneNode::NzSceneNode() : m_scene(nullptr), +m_boundingVolumeUpdated(false), m_drawingEnabled(true), m_visible(false) { @@ -19,6 +20,7 @@ m_visible(false) NzSceneNode::NzSceneNode(const NzSceneNode& sceneNode) : NzNode(sceneNode), m_scene(nullptr), +m_boundingVolumeUpdated(false), m_drawingEnabled(sceneNode.m_drawingEnabled), m_visible(false) { @@ -44,6 +46,14 @@ NzVector3f NzSceneNode::GetBackward() const return NzNode::GetBackward(); } +const NzBoundingVolumef& NzSceneNode::GetBoundingVolume() const +{ + if (!m_boundingVolumeUpdated) + UpdateBoundingVolume(); + + return m_boundingVolume; +} + NzVector3f NzSceneNode::GetDown() const { if (m_scene) @@ -83,6 +93,11 @@ NzVector3f NzSceneNode::GetLeft() const return NzNode::GetLeft(); } +const NzString& NzSceneNode::GetName() const +{ + return m_name; +} + nzNodeType NzSceneNode::GetNodeType() const { return nzNodeType_Scene; @@ -129,6 +144,19 @@ bool NzSceneNode::IsVisible() const return m_visible; } +bool NzSceneNode::SetName(const NzString& name) +{ + if (m_scene) + // On demande à la scène de changer notre nom + return m_scene->ChangeNodeName(this, name); + else + { + // Pas de scène ? Changeons notre nom nous-même + SetNameInternal(name); + return true; + } +} + NzSceneNode& NzSceneNode::operator=(const NzSceneNode& sceneNode) { NzNode::operator=(sceneNode); @@ -145,6 +173,13 @@ bool NzSceneNode::FrustumCull(const NzFrustumf& frustum) const return frustum.Contains(GetBoundingVolume()); } +void NzSceneNode::InvalidateNode() +{ + NzNode::InvalidateNode(); + + m_boundingVolumeUpdated = false; +} + void NzSceneNode::OnParenting(const NzNode* parent) { if (parent) @@ -184,6 +219,11 @@ void NzSceneNode::Register() { } +void NzSceneNode::SetNameInternal(const NzString& name) +{ + m_name = name; +} + void NzSceneNode::SetScene(NzScene* scene) { if (m_scene != scene) @@ -207,6 +247,18 @@ void NzSceneNode::Update() { } +void NzSceneNode::UpdateBoundingVolume() const +{ + if (m_boundingVolume.IsNull()) + MakeBoundingVolume(); + + if (!m_transformMatrixUpdated) + UpdateTransformMatrix(); + + m_boundingVolume.Update(m_transformMatrix); + m_boundingVolumeUpdated = true; +} + void NzSceneNode::UpdateVisibility(const NzFrustumf& frustum) { bool wasVisible = m_visible; diff --git a/src/Nazara/Graphics/SceneRoot.cpp b/src/Nazara/Graphics/SceneRoot.cpp index e817f511f..7cd3b7741 100644 --- a/src/Nazara/Graphics/SceneRoot.cpp +++ b/src/Nazara/Graphics/SceneRoot.cpp @@ -20,12 +20,6 @@ void NzSceneRoot::AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const NazaraInternalError("SceneNode::AddToRenderQueue() called on SceneRoot"); } -const NzBoundingVolumef& NzSceneRoot::GetBoundingVolume() const -{ - static NzBoundingVolumef infinite(nzExtend_Infinite); - return infinite; -} - nzSceneNodeType NzSceneRoot::GetSceneNodeType() const { return nzSceneNodeType_Root; @@ -36,6 +30,23 @@ bool NzSceneRoot::IsDrawable() const return true; } +NzSceneRoot* NzSceneRoot::Clone() const +{ + NazaraInternalError("SceneNode::Clone() called on SceneRoot"); + return nullptr; +} + +NzSceneRoot* NzSceneRoot::Create() const +{ + NazaraInternalError("SceneNode::Create() called on SceneRoot"); + return nullptr; +} + +void NzSceneRoot::MakeBoundingVolume() const +{ + m_boundingVolume.MakeInfinite(); +} + void NzSceneRoot::Register() { NazaraInternalError("SceneNode::Register() called on SceneRoot"); diff --git a/src/Nazara/Graphics/SkeletalModel.cpp b/src/Nazara/Graphics/SkeletalModel.cpp index 1f9cba729..94af428b6 100644 --- a/src/Nazara/Graphics/SkeletalModel.cpp +++ b/src/Nazara/Graphics/SkeletalModel.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -106,6 +107,16 @@ void NzSkeletalModel::AdvanceAnimation(float elapsedTime) InvalidateBoundingVolume(); } +NzSkeletalModel* NzSkeletalModel::Clone() const +{ + return new NzSkeletalModel(*this); +} + +NzSkeletalModel* NzSkeletalModel::Create() const +{ + return new NzSkeletalModel; +} + void NzSkeletalModel::EnableAnimation(bool animation) { m_animationEnabled = animation; @@ -317,6 +328,11 @@ NzSkeletalModel& NzSkeletalModel::operator=(NzSkeletalModel&& node) return *this; } +void NzSkeletalModel::MakeBoundingVolume() const +{ + m_boundingVolume.Set(m_skeleton.GetAABB()); +} + void NzSkeletalModel::Register() { m_scene->RegisterForUpdate(this); @@ -333,16 +349,4 @@ void NzSkeletalModel::Update() AdvanceAnimation(m_scene->GetUpdateTime()); } -void NzSkeletalModel::UpdateBoundingVolume() const -{ - if (m_boundingVolume.IsNull()) - m_boundingVolume.Set(m_skeleton.GetAABB()); - - if (!m_transformMatrixUpdated) - UpdateTransformMatrix(); - - m_boundingVolume.Update(m_transformMatrix); - m_boundingVolumeUpdated = true; -} - NzSkeletalModelLoader::LoaderList NzSkeletalModel::s_loaders; diff --git a/src/Nazara/Graphics/Sprite.cpp b/src/Nazara/Graphics/Sprite.cpp index 426f51321..7182e20bd 100644 --- a/src/Nazara/Graphics/Sprite.cpp +++ b/src/Nazara/Graphics/Sprite.cpp @@ -3,28 +3,26 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include +#include #include #include #include NzSprite::NzSprite() : -m_boundingVolume(NzBoundingVolumef::Null()), m_color(NzColor::White), m_textureCoords(0.f, 0.f, 1.f, 1.f), m_size(64.f, 64.f), -m_boundingVolumeUpdated(true), m_verticesUpdated(false) { SetDefaultMaterial(); } NzSprite::NzSprite(NzTexture* texture) : -m_boundingVolume(NzBoundingVolumef::Null()), m_color(NzColor::White), m_textureCoords(0.f, 0.f, 1.f, 1.f), m_size(64.f, 64.f), -m_boundingVolumeUpdated(false), m_verticesUpdated(false) { SetTexture(texture, true); @@ -32,13 +30,11 @@ m_verticesUpdated(false) NzSprite::NzSprite(const NzSprite& sprite) : NzSceneNode(sprite), -m_boundingVolume(sprite.m_boundingVolume), m_color(sprite.m_color), m_material(sprite.m_material), m_textureCoords(sprite.m_textureCoords), m_size(sprite.m_size), m_vertices(sprite.m_vertices), -m_boundingVolumeUpdated(sprite.m_boundingVolumeUpdated), m_verticesUpdated(sprite.m_verticesUpdated) { SetParent(sprite.GetParent()); @@ -52,12 +48,14 @@ void NzSprite::AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const renderQueue->AddSprites(m_material, m_vertices, 1); } -const NzBoundingVolumef& NzSprite::GetBoundingVolume() const +NzSprite* NzSprite::Clone() const { - if (!m_boundingVolumeUpdated) - UpdateBoundingVolume(); + return new NzSprite(*this); +} - return m_boundingVolume; +NzSprite* NzSprite::Create() const +{ + return new NzSprite; } const NzColor& NzSprite::GetColor() const @@ -189,7 +187,6 @@ NzSprite& NzSprite::operator=(const NzSprite& sprite) m_size = sprite.m_size; // On ne copie pas les sommets finaux car il est très probable que nos paramètres soient modifiés et qu'ils doivent être régénérés de toute façon - m_boundingVolumeUpdated = false; m_verticesUpdated = false; return *this; @@ -199,7 +196,6 @@ void NzSprite::InvalidateNode() { NzSceneNode::InvalidateNode(); - m_boundingVolumeUpdated = false; m_verticesUpdated = false; } @@ -213,21 +209,12 @@ void NzSprite::Unregister() { } -void NzSprite::UpdateBoundingVolume() const +void NzSprite::MakeBoundingVolume() const { - if (m_boundingVolume.IsNull()) - { - NzVector3f down = m_scene->GetDown(); - NzVector3f right = m_scene->GetRight(); + NzVector3f down = (m_scene) ? m_scene->GetDown() : NzVector3f::Down(); + NzVector3f right = (m_scene) ? m_scene->GetRight() : NzVector3f::Right(); - m_boundingVolume.Set(NzVector3f(0.f), m_size.x*right + m_size.y*down); - } - - if (!m_transformMatrixUpdated) - UpdateTransformMatrix(); - - m_boundingVolume.Update(m_transformMatrix); - m_boundingVolumeUpdated = true; + m_boundingVolume.Set(NzVector3f(0.f), m_size.x*right + m_size.y*down); } void NzSprite::UpdateVertices() const @@ -235,8 +222,8 @@ void NzSprite::UpdateVertices() const if (!m_transformMatrixUpdated) UpdateTransformMatrix(); - NzVector3f down = m_scene->GetDown(); - NzVector3f right = m_scene->GetRight(); + NzVector3f down = (m_scene) ? m_scene->GetDown() : NzVector3f::Down(); + NzVector3f right = (m_scene) ? m_scene->GetRight() : NzVector3f::Right(); m_vertices[0].color = m_color; m_vertices[0].position = m_transformMatrix.Transform(NzVector3f(0.f)); diff --git a/src/Nazara/Graphics/TextSprite.cpp b/src/Nazara/Graphics/TextSprite.cpp index 41766ec97..099709dd8 100644 --- a/src/Nazara/Graphics/TextSprite.cpp +++ b/src/Nazara/Graphics/TextSprite.cpp @@ -5,13 +5,14 @@ #include #include #include +#include #include +#include #include #include #include NzTextSprite::NzTextSprite() : -m_boundingVolume(NzBoundingVolumef::Null()), m_color(NzColor::White), m_verticesUpdated(false) { @@ -24,11 +25,9 @@ m_atlases(sprite.m_atlases), m_renderInfos(sprite.m_renderInfos), m_localVertices(sprite.m_localVertices), m_vertices(sprite.m_vertices), -m_boundingVolume(sprite.m_boundingVolume), m_color(sprite.m_color), m_material(sprite.m_material), m_localBounds(sprite.m_localBounds), -m_boundingVolumeUpdated(sprite.m_boundingVolumeUpdated), m_verticesUpdated(sprite.m_verticesUpdated) { SetParent(sprite.GetParent()); @@ -66,12 +65,14 @@ void NzTextSprite::Clear() m_vertices.clear(); } -const NzBoundingVolumef& NzTextSprite::GetBoundingVolume() const +NzTextSprite* NzTextSprite::Clone() const { - if (!m_boundingVolumeUpdated) - UpdateBoundingVolume(); + return new NzTextSprite(*this); +} - return m_boundingVolume; +NzTextSprite* NzTextSprite::Create() const +{ + return new NzTextSprite; } const NzColor& NzTextSprite::GetColor() const @@ -266,7 +267,6 @@ NzTextSprite& NzTextSprite::operator=(const NzTextSprite& text) m_localVertices = text.m_localVertices; // On ne copie pas les sommets finaux car il est très probable que nos paramètres soient modifiés et qu'ils doivent être régénérés de toute façon - m_boundingVolumeUpdated = false; m_verticesUpdated = false; return *this; @@ -284,10 +284,21 @@ void NzTextSprite::InvalidateNode() { NzSceneNode::InvalidateNode(); - m_boundingVolumeUpdated = false; m_verticesUpdated = false; } +void NzTextSprite::MakeBoundingVolume() const +{ + NzVector3f down = (m_scene) ? m_scene->GetDown() : NzVector3f::Down(); + NzVector3f right = (m_scene) ? m_scene->GetRight() : NzVector3f::Right(); + + NzRectf bounds(m_localBounds); + NzVector2f max = bounds.GetMaximum(); + NzVector2f min = bounds.GetMinimum(); + + m_boundingVolume.Set(min.x*right + min.y*down, max.x*right + max.y*down); +} + bool NzTextSprite::OnAtlasCleared(const NzAbstractAtlas* atlas, void* userdata) { NazaraUnused(userdata); @@ -373,34 +384,13 @@ void NzTextSprite::Unregister() { } -void NzTextSprite::UpdateBoundingVolume() const -{ - if (m_boundingVolume.IsNull()) - { - NzVector3f down = m_scene->GetDown(); - NzVector3f right = m_scene->GetRight(); - - NzRectf bounds(m_localBounds); - NzVector2f max = bounds.GetMaximum(); - NzVector2f min = bounds.GetMinimum(); - - m_boundingVolume.Set(min.x*right + min.y*down, max.x*right + max.y*down); - } - - if (!m_transformMatrixUpdated) - UpdateTransformMatrix(); - - m_boundingVolume.Update(m_transformMatrix); - m_boundingVolumeUpdated = true; -} - void NzTextSprite::UpdateVertices() const { if (!m_transformMatrixUpdated) UpdateTransformMatrix(); - NzVector3f down = m_scene->GetDown(); - NzVector3f right = m_scene->GetRight(); + NzVector3f down = (m_scene) ? m_scene->GetDown() : NzVector3f::Down(); + NzVector3f right = (m_scene) ? m_scene->GetRight() : NzVector3f::Right(); NzSparsePtr colorPtr(&m_vertices[0].color, sizeof(NzVertexStruct_XYZ_Color_UV)); NzSparsePtr posPtr(&m_vertices[0].position, sizeof(NzVertexStruct_XYZ_Color_UV)); diff --git a/src/Nazara/Utility/Node.cpp b/src/Nazara/Utility/Node.cpp index 6fb44b666..2d7661e7a 100644 --- a/src/Nazara/Utility/Node.cpp +++ b/src/Nazara/Utility/Node.cpp @@ -125,11 +125,6 @@ NzVector3f NzNode::GetLeft() const return m_derivedRotation * NzVector3f::Left(); } -const NzString& NzNode::GetName() const -{ - return m_name; -} - nzNodeType NzNode::GetNodeType() const { return nzNodeType_Default; @@ -413,11 +408,6 @@ void NzNode::SetInitialScale(float scaleX, float scaleY, float scaleZ) InvalidateNode(); } -void NzNode::SetName(const NzString& name) -{ - m_name = name; -} - void NzNode::SetParent(const NzNode* node, bool keepDerived) { #if NAZARA_UTILITY_SAFE @@ -621,7 +611,6 @@ NzNode& NzNode::operator=(const NzNode& node) m_initialPosition = node.m_initialPosition; m_initialRotation = node.m_initialRotation; m_initialScale = node.m_initialScale; - m_name = node.m_name; m_position = node.m_position; m_rotation = node.m_rotation; m_scale = node.m_scale;