diff --git a/Resources/Editor/Models/Arrow.fbx b/Resources/Editor/Models/Arrow.fbx
deleted file mode 100644
index d7941931..00000000
Binary files a/Resources/Editor/Models/Arrow.fbx and /dev/null differ
diff --git a/Resources/Editor/Models/Arrow_Rotate.fbx b/Resources/Editor/Models/Arrow_Rotate.fbx
new file mode 100644
index 00000000..0aaadb2f
Binary files /dev/null and b/Resources/Editor/Models/Arrow_Rotate.fbx differ
diff --git a/Resources/Editor/Models/Arrow_Scale.fbx b/Resources/Editor/Models/Arrow_Scale.fbx
new file mode 100644
index 00000000..eff044eb
Binary files /dev/null and b/Resources/Editor/Models/Arrow_Scale.fbx differ
diff --git a/Resources/Editor/Models/Arrow_Translate.fbx b/Resources/Editor/Models/Arrow_Translate.fbx
new file mode 100644
index 00000000..7a52a0ec
Binary files /dev/null and b/Resources/Editor/Models/Arrow_Translate.fbx differ
diff --git a/Sources/Overload/OvAnalytics/OvAnalytics.vcxproj b/Sources/Overload/OvAnalytics/OvAnalytics.vcxproj
index 2c0a6880..72a680c1 100644
--- a/Sources/Overload/OvAnalytics/OvAnalytics.vcxproj
+++ b/Sources/Overload/OvAnalytics/OvAnalytics.vcxproj
@@ -14,19 +14,19 @@
15.0
{45BFDD00-877F-42ED-A0E4-92E56F7D3C0E}
OvAnalytics
- 10.0.17763.0
+ 10.0
DynamicLibrary
true
- v141
+ v142
MultiByte
DynamicLibrary
false
- v141
+ v142
true
MultiByte
diff --git a/Sources/Overload/OvAudio/OvAudio.vcxproj b/Sources/Overload/OvAudio/OvAudio.vcxproj
index 54da97b1..5d5acb78 100644
--- a/Sources/Overload/OvAudio/OvAudio.vcxproj
+++ b/Sources/Overload/OvAudio/OvAudio.vcxproj
@@ -14,19 +14,19 @@
15.0
{E76098C7-D1C1-430E-A7B2-527CF45BD853}
OvAudio
- 10.0.17763.0
+ 10.0
DynamicLibrary
true
- v141
+ v142
MultiByte
DynamicLibrary
false
- v141
+ v142
true
MultiByte
diff --git a/Sources/Overload/OvCore/OvCore.vcxproj b/Sources/Overload/OvCore/OvCore.vcxproj
index eb8527ce..8e0321e1 100644
--- a/Sources/Overload/OvCore/OvCore.vcxproj
+++ b/Sources/Overload/OvCore/OvCore.vcxproj
@@ -14,19 +14,19 @@
15.0
{C1D2EBB7-EE2A-4D42-858B-F14F5A47B867}
OvCore
- 10.0.17763.0
+ 10.0
DynamicLibrary
true
- v141
+ v142
MultiByte
DynamicLibrary
false
- v141
+ v142
true
MultiByte
@@ -123,7 +123,7 @@ xcopy "$(SolutionDir)..\..\Build\OvWindowing\bin\$(Configuration)\*.dll" "$(Solu
xcopy "$(SolutionDir)..\..\Build\OvWindowing\lib\$(Configuration)\*.lib" "$(SolutionDir)..\..\Build\$(ProjectName)\lib\$(Configuration)" /e /y /i /r
- liblua53.a;OvMaths.lib;OvPhysics.lib;OvRendering.lib;OvTools.lib;OvUI.lib;OvAudio.lib;OvDebug.lib;OvWindowing.lib;%(AdditionalDependencies)
+ liblua53.a;OvMaths.lib;OvPhysics.lib;OvRendering.lib;OvTools.lib;OvUI.lib;OvAudio.lib;OvDebug.lib;OvWindowing.lib;OvAnalytics.lib;%(AdditionalDependencies)
@@ -140,7 +140,7 @@ xcopy "$(SolutionDir)..\..\Build\OvWindowing\lib\$(Configuration)\*.lib" "$(Solu
true
true
- liblua53.a;OvMaths.lib;OvPhysics.lib;OvRendering.lib;OvTools.lib;OvUI.lib;OvAudio.lib;OvDebug.lib;OvWindowing.lib;%(AdditionalDependencies)
+ liblua53.a;OvMaths.lib;OvPhysics.lib;OvRendering.lib;OvTools.lib;OvUI.lib;OvAudio.lib;OvDebug.lib;OvWindowing.lib;OvAnalytics.lib;%(AdditionalDependencies)
RD /S /Q "$(SolutionDir)..\..\Build\$(ProjectName)\include"
diff --git a/Sources/Overload/OvCore/include/OvCore/ECS/Components/Behaviour.inl b/Sources/Overload/OvCore/include/OvCore/ECS/Components/Behaviour.inl
index 5ea50945..76605033 100644
--- a/Sources/Overload/OvCore/include/OvCore/ECS/Components/Behaviour.inl
+++ b/Sources/Overload/OvCore/include/OvCore/ECS/Components/Behaviour.inl
@@ -6,6 +6,9 @@
#pragma once
+
+#include
+
#include "OvCore/ECS/Components/Behaviour.h"
namespace OvCore::ECS::Components
diff --git a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CCamera.h b/Sources/Overload/OvCore/include/OvCore/ECS/Components/CCamera.h
index 4e3c2476..0e435a40 100644
--- a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CCamera.h
+++ b/Sources/Overload/OvCore/include/OvCore/ECS/Components/CCamera.h
@@ -35,18 +35,6 @@ namespace OvCore::ECS::Components
*/
std::string GetName() override;
- /**
- * Returns the projection matrix
- * @param p_windowWidth
- * @param p_windowHeight
- */
- OvMaths::FMatrix4 GetProjectionMatrix(uint16_t p_windowWidth, uint16_t p_windowHeight);
-
- /**
- * Returns the view matrix
- */
- OvMaths::FMatrix4 GetViewMatrix();
-
/**
* Sets the fov of the camera to the given value
* @param p_value
@@ -71,6 +59,18 @@ namespace OvCore::ECS::Components
*/
void SetClearColor(const OvMaths::FVector3& p_clearColor);
+ /**
+ * Defines if the camera should apply frustum geometry culling in rendering
+ * @param p_enable
+ */
+ void SetFrustumGeometryCulling(bool p_enable);
+
+ /**
+ * Defines if the camera should apply frustum light culling in rendering
+ * @param p_enable
+ */
+ void SetFrustumLightCulling(bool p_enable);
+
/**
* Returns the fov of the camera
*/
@@ -91,6 +91,16 @@ namespace OvCore::ECS::Components
*/
const OvMaths::FVector3& GetClearColor() const;
+ /**
+ * Returns true if the frustum geometry culling is enabled
+ */
+ bool HasFrustumGeometryCulling() const;
+
+ /**
+ * Returns true if the frustum light culling is enabled
+ */
+ bool HasFrustumLightCulling() const;
+
/**
* Returns the OvRendering camera instance attached to this component
*/
diff --git a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CModelRenderer.h b/Sources/Overload/OvCore/include/OvCore/ECS/Components/CModelRenderer.h
index 6af09db8..e62a7086 100644
--- a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CModelRenderer.h
+++ b/Sources/Overload/OvCore/include/OvCore/ECS/Components/CModelRenderer.h
@@ -21,6 +21,17 @@ namespace OvCore::ECS::Components
class API_OVCORE CModelRenderer : public AComponent
{
public:
+ /**
+ * Defines how the model renderer bounding sphere should be interpreted
+ */
+ enum class EFrustumBehaviour
+ {
+ DISABLED = 0,
+ CULL_MODEL = 1,
+ CULL_MESHES = 2,
+ CULL_CUSTOM = 3
+ };
+
/**
* Constructor
* @param p_owner
@@ -43,6 +54,28 @@ namespace OvCore::ECS::Components
*/
OvRendering::Resources::Model* GetModel() const;
+ /**
+ * Sets a bounding mode
+ * @param p_boundingMode
+ */
+ void SetFrustumBehaviour(EFrustumBehaviour p_boundingMode);
+
+ /**
+ * Returns the current bounding mode
+ */
+ EFrustumBehaviour GetFrustumBehaviour() const;
+
+ /**
+ * Returns the custom bounding sphere
+ */
+ const OvRendering::Geometry::BoundingSphere& GetCustomBoundingSphere() const;
+
+ /**
+ * Sets the custom bounding sphere
+ * @param p_boundingSphere
+ */
+ void SetCustomBoundingSphere(const OvRendering::Geometry::BoundingSphere& p_boundingSphere);
+
/**
* Serialize the component
* @param p_doc
@@ -66,5 +99,7 @@ namespace OvCore::ECS::Components
private:
OvRendering::Resources::Model* m_model = nullptr;
OvTools::Eventing::Event<> m_modelChangedEvent;
+ OvRendering::Geometry::BoundingSphere m_customBoundingSphere = { {}, 1.0f };
+ EFrustumBehaviour m_frustumBehaviour = EFrustumBehaviour::CULL_MODEL;
};
}
\ No newline at end of file
diff --git a/Sources/Overload/OvCore/include/OvCore/ECS/Renderer.h b/Sources/Overload/OvCore/include/OvCore/ECS/Renderer.h
index 4fc74fe5..95eb262b 100644
--- a/Sources/Overload/OvCore/include/OvCore/ECS/Renderer.h
+++ b/Sources/Overload/OvCore/include/OvCore/ECS/Renderer.h
@@ -10,6 +10,7 @@
#include
#include
+#include
#include "OvCore/API/Export.h"
#include "OvCore/Resources/Material.h"
@@ -51,29 +52,60 @@ namespace OvCore::ECS
/**
* Fill the given FMatrix4 vector with lights information
* @param p_scene
- * @param p_out
*/
- void FindLightMatrices(const OvCore::SceneSystem::Scene& p_scene, std::vector& p_out);
+ std::vector FindLightMatrices(const OvCore::SceneSystem::Scene& p_scene);
+
+ /**
+ * Fill the given FMatrix4 vector with lights information that are inside the frustum
+ * @param p_scene
+ * @param p_frustum
+ */
+ std::vector FindLightMatricesInFrustum(const OvCore::SceneSystem::Scene& p_scene, const OvRendering::Data::Frustum& p_frustum);
/**
* Draw the given scene using the given default material (optional) if no material found on an actor
* @param p_scene
* @param p_cameraPosition
+ * @param p_camera
+ * @param p_customFrustum
+ * @param p_defaultMaterial
+ */
+ void RenderScene
+ (
+ OvCore::SceneSystem::Scene& p_scene,
+ const OvMaths::FVector3& p_cameraPosition,
+ const OvRendering::LowRenderer::Camera& p_camera,
+ const OvRendering::Data::Frustum* p_customFrustum = nullptr,
+ OvCore::Resources::Material* p_defaultMaterial = nullptr
+ );
+
+ /**
+ * Returns opaque and transparents drawables from the scene with frustum culling
+ * @param p_scene
+ * @param p_cameraPosition
+ * @param p_frustum
* @param p_defaultMaterial
*/
- void RenderScene(OvCore::SceneSystem::Scene& p_scene, const OvMaths::FVector3& p_cameraPosition, Resources::Material* p_defaultMaterial = nullptr);
+ std::pair FindAndSortFrustumCulledDrawables
+ (
+ const OvCore::SceneSystem::Scene& p_scene,
+ const OvMaths::FVector3& p_cameraPosition,
+ const OvRendering::Data::Frustum& p_frustum,
+ OvCore::Resources::Material* p_defaultMaterial
+ );
/**
- * Find every drawables objects in the scene. Sorting order:
- * - Opaques (Front to back)
- * - Transparents (Back to front)
- * @param p_opaques
- * @param p_transparents
+ * Returns opaque and transparents drawables from the scene
* @param p_scene
* @param p_cameraPosition
* @param p_defaultMaterial
*/
- void FindAndSortDrawables(OpaqueDrawables& p_opaques, TransparentDrawables& p_transparents, const OvCore::SceneSystem::Scene& p_scene, const OvMaths::FVector3& p_cameraPosition, Resources::Material* p_defaultMaterial = nullptr);
+ std::pair FindAndSortDrawables
+ (
+ const OvCore::SceneSystem::Scene& p_scene,
+ const OvMaths::FVector3& p_cameraPosition,
+ OvCore::Resources::Material* p_defaultMaterial
+ );
/**
* Draw a Drawable instance
diff --git a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CCamera.cpp b/Sources/Overload/OvCore/src/OvCore/ECS/Components/CCamera.cpp
index 9a2b5a27..b833f199 100644
--- a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CCamera.cpp
+++ b/Sources/Overload/OvCore/src/OvCore/ECS/Components/CCamera.cpp
@@ -35,17 +35,6 @@ std::string OvCore::ECS::Components::CCamera::GetName()
return "Camera";
}
-
-OvMaths::FMatrix4 OvCore::ECS::Components::CCamera::GetProjectionMatrix(uint16_t p_windowWidth, uint16_t p_windowHeight)
-{
- return m_camera.GetProjectionMatrix(p_windowWidth, p_windowHeight);
-}
-
-OvMaths::FMatrix4 OvCore::ECS::Components::CCamera::GetViewMatrix()
-{
- return m_camera.GetViewMatrix(owner.transform.GetWorldPosition());
-}
-
void OvCore::ECS::Components::CCamera::SetFov(float p_value)
{
m_camera.SetFov(p_value);
@@ -61,6 +50,16 @@ void OvCore::ECS::Components::CCamera::SetFar(float p_value)
m_camera.SetFar(p_value);
}
+void OvCore::ECS::Components::CCamera::SetFrustumGeometryCulling(bool p_enable)
+{
+ m_camera.SetFrustumGeometryCulling(p_enable);
+}
+
+void OvCore::ECS::Components::CCamera::SetFrustumLightCulling(bool p_enable)
+{
+ m_camera.SetFrustumLightCulling(p_enable);
+}
+
float OvCore::ECS::Components::CCamera::GetFov() const
{
return m_camera.GetFov();
@@ -81,11 +80,21 @@ const OvMaths::FVector3 & OvCore::ECS::Components::CCamera::GetClearColor() cons
return m_camera.GetClearColor();
}
+bool OvCore::ECS::Components::CCamera::HasFrustumGeometryCulling() const
+{
+ return m_camera.HasFrustumGeometryCulling();
+}
+
void OvCore::ECS::Components::CCamera::SetClearColor(const OvMaths::FVector3 & p_clearColor)
{
m_camera.SetClearColor(p_clearColor);
}
+bool OvCore::ECS::Components::CCamera::HasFrustumLightCulling() const
+{
+ return m_camera.HasFrustumLightCulling();
+}
+
OvRendering::LowRenderer::Camera & OvCore::ECS::Components::CCamera::GetCamera()
{
return m_camera;
@@ -97,6 +106,8 @@ void OvCore::ECS::Components::CCamera::OnSerialize(tinyxml2::XMLDocument & p_doc
OvCore::Helpers::Serializer::SerializeFloat(p_doc, p_node, "near", m_camera.GetNear());
OvCore::Helpers::Serializer::SerializeFloat(p_doc, p_node, "far", m_camera.GetFar());
OvCore::Helpers::Serializer::SerializeVec3(p_doc, p_node, "clear_color", m_camera.GetClearColor());
+ OvCore::Helpers::Serializer::SerializeBoolean(p_doc, p_node, "frustum_geometry_culling", m_camera.HasFrustumGeometryCulling());
+ OvCore::Helpers::Serializer::SerializeBoolean(p_doc, p_node, "frustum_light_culling", m_camera.HasFrustumLightCulling());
}
void OvCore::ECS::Components::CCamera::OnDeserialize(tinyxml2::XMLDocument & p_doc, tinyxml2::XMLNode * p_node)
@@ -104,7 +115,9 @@ void OvCore::ECS::Components::CCamera::OnDeserialize(tinyxml2::XMLDocument & p_d
m_camera.SetFov(OvCore::Helpers::Serializer::DeserializeFloat(p_doc, p_node, "fov"));
m_camera.SetNear(OvCore::Helpers::Serializer::DeserializeFloat(p_doc, p_node, "near"));
m_camera.SetFar(OvCore::Helpers::Serializer::DeserializeFloat(p_doc, p_node, "far"));
- SetClearColor(OvCore::Helpers::Serializer::DeserializeVec3(p_doc, p_node, "clear_color"));
+ m_camera.SetClearColor(OvCore::Helpers::Serializer::DeserializeVec3(p_doc, p_node, "clear_color"));
+ m_camera.SetFrustumGeometryCulling(OvCore::Helpers::Serializer::DeserializeBoolean(p_doc, p_node, "frustum_geometry_culling"));
+ m_camera.SetFrustumLightCulling(OvCore::Helpers::Serializer::DeserializeBoolean(p_doc, p_node, "frustum_light_culling"));
}
void OvCore::ECS::Components::CCamera::OnInspector(OvUI::Internal::WidgetContainer& p_root)
@@ -113,4 +126,6 @@ void OvCore::ECS::Components::CCamera::OnInspector(OvUI::Internal::WidgetContain
OvCore::Helpers::GUIDrawer::DrawScalar(p_root, "Near", std::bind(&CCamera::GetNear, this), std::bind(&CCamera::SetNear, this, std::placeholders::_1));
OvCore::Helpers::GUIDrawer::DrawScalar(p_root, "Far", std::bind(&CCamera::GetFar, this), std::bind(&CCamera::SetFar, this, std::placeholders::_1));
OvCore::Helpers::GUIDrawer::DrawColor(p_root, "Clear color", [this]() {return reinterpret_cast(GetClearColor()); }, [this](OvUI::Types::Color p_color) { SetClearColor({ p_color.r, p_color.g, p_color.b }); }, false);
+ OvCore::Helpers::GUIDrawer::DrawBoolean(p_root, "Frustum Geometry Culling", std::bind(&CCamera::HasFrustumGeometryCulling, this), std::bind(&CCamera::SetFrustumGeometryCulling, this, std::placeholders::_1));
+ OvCore::Helpers::GUIDrawer::DrawBoolean(p_root, "Frustum Light Culling", std::bind(&CCamera::HasFrustumLightCulling, this), std::bind(&CCamera::SetFrustumLightCulling, this, std::placeholders::_1));
}
diff --git a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CModelRenderer.cpp b/Sources/Overload/OvCore/src/OvCore/ECS/Components/CModelRenderer.cpp
index a7b22460..7451a978 100644
--- a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CModelRenderer.cpp
+++ b/Sources/Overload/OvCore/src/OvCore/ECS/Components/CModelRenderer.cpp
@@ -5,8 +5,12 @@
*/
#include
+#include
#include
#include
+#include
+#include
+#include
#include "OvCore/Global/ServiceLocator.h"
#include "OvCore/ResourceManagement/TextureManager.h"
@@ -41,17 +45,71 @@ OvRendering::Resources::Model * OvCore::ECS::Components::CModelRenderer::GetMode
return m_model;
}
+void OvCore::ECS::Components::CModelRenderer::SetFrustumBehaviour(EFrustumBehaviour p_boundingMode)
+{
+ m_frustumBehaviour = p_boundingMode;
+}
+
+OvCore::ECS::Components::CModelRenderer::EFrustumBehaviour OvCore::ECS::Components::CModelRenderer::GetFrustumBehaviour() const
+{
+ return m_frustumBehaviour;
+}
+
+const OvRendering::Geometry::BoundingSphere& OvCore::ECS::Components::CModelRenderer::GetCustomBoundingSphere() const
+{
+ return m_customBoundingSphere;
+}
+
+void OvCore::ECS::Components::CModelRenderer::SetCustomBoundingSphere(const OvRendering::Geometry::BoundingSphere& p_boundingSphere)
+{
+ m_customBoundingSphere = p_boundingSphere;
+}
+
void OvCore::ECS::Components::CModelRenderer::OnSerialize(tinyxml2::XMLDocument & p_doc, tinyxml2::XMLNode * p_node)
{
OvCore::Helpers::Serializer::SerializeModel(p_doc, p_node, "model", m_model);
+ OvCore::Helpers::Serializer::SerializeInt(p_doc, p_node, "frustum_behaviour", reinterpret_cast(m_frustumBehaviour));
+ OvCore::Helpers::Serializer::SerializeVec3(p_doc, p_node, "custom_bounding_sphere_position", m_customBoundingSphere.position);
+ OvCore::Helpers::Serializer::SerializeFloat(p_doc, p_node, "custom_bounding_sphere_radius", m_customBoundingSphere.radius);
}
void OvCore::ECS::Components::CModelRenderer::OnDeserialize(tinyxml2::XMLDocument & p_doc, tinyxml2::XMLNode* p_node)
{
OvCore::Helpers::Serializer::DeserializeModel(p_doc, p_node, "model", m_model);
+ OvCore::Helpers::Serializer::DeserializeInt(p_doc, p_node, "frustum_behaviour", reinterpret_cast(m_frustumBehaviour));
+ OvCore::Helpers::Serializer::DeserializeVec3(p_doc, p_node, "custom_bounding_sphere_position", m_customBoundingSphere.position);
+ OvCore::Helpers::Serializer::DeserializeFloat(p_doc, p_node, "custom_bounding_sphere_radius", m_customBoundingSphere.radius);
}
void OvCore::ECS::Components::CModelRenderer::OnInspector(OvUI::Internal::WidgetContainer& p_root)
{
- OvCore::Helpers::GUIDrawer::DrawMesh(p_root, "Model", m_model, &m_modelChangedEvent);
+ using namespace OvCore::Helpers;
+
+ GUIDrawer::DrawMesh(p_root, "Model", m_model, &m_modelChangedEvent);
+
+ GUIDrawer::CreateTitle(p_root, "Frustum Culling Behaviour");
+ auto& boundingMode = p_root.CreateWidget(0);
+ boundingMode.choices.emplace(0, "Disabled");
+ boundingMode.choices.emplace(1, "Cull model");
+ boundingMode.choices.emplace(2, "Cull model & sub-meshes");
+ boundingMode.choices.emplace(3, "Cull custom bounding sphere");
+ auto& boundingModeDispatcher = boundingMode.AddPlugin>();
+ boundingModeDispatcher.RegisterReference(reinterpret_cast(m_frustumBehaviour));
+
+ auto& centerLabel = p_root.CreateWidget("Bounding Sphere Center", GUIDrawer::TitleColor);
+ auto& centerWidget = p_root.CreateWidget>(GUIDrawer::GetDataType(), GUIDrawer::_MIN_FLOAT, GUIDrawer::_MAX_FLOAT, 0.f, 0.05f, "", GUIDrawer::GetFormat());
+ auto& centerDispatcher = centerWidget.AddPlugin>>();
+ centerDispatcher.RegisterReference(reinterpret_cast&>(m_customBoundingSphere.position));
+
+ auto& radiusLabel = p_root.CreateWidget("Bounding Sphere Radius", GUIDrawer::TitleColor);
+ auto& radiusWidget = p_root.CreateWidget(0.0f, GUIDrawer::_MAX_FLOAT, 0.f, 0.1f);
+ auto& radiusDispatcher = radiusWidget.AddPlugin>();
+ radiusDispatcher.RegisterReference(m_customBoundingSphere.radius);
+
+ boundingMode.ValueChangedEvent += [&](int p_choice)
+ {
+ centerLabel.enabled = centerWidget.enabled = radiusLabel.enabled = radiusWidget.enabled = p_choice == 3;
+ };
+
+ centerLabel.enabled = centerWidget.enabled = radiusLabel.enabled = radiusWidget.enabled = m_frustumBehaviour == EFrustumBehaviour::CULL_CUSTOM;
}
diff --git a/Sources/Overload/OvCore/src/OvCore/ECS/Renderer.cpp b/Sources/Overload/OvCore/src/OvCore/ECS/Renderer.cpp
index 869f7faf..d52da5f5 100644
--- a/Sources/Overload/OvCore/src/OvCore/ECS/Renderer.cpp
+++ b/Sources/Overload/OvCore/src/OvCore/ECS/Renderer.cpp
@@ -4,7 +4,10 @@
* @restrictions: This software may not be resold, redistributed or otherwise conveyed to a third party.
*/
+#include
+
#include
+#include
#include "OvCore/ECS/Renderer.h"
#include "OvCore/ECS/Components/CModelRenderer.h"
@@ -36,30 +39,87 @@ OvCore::ECS::Components::CCamera* OvCore::ECS::Renderer::FindMainCamera(const Ov
return nullptr;
}
-void OvCore::ECS::Renderer::FindLightMatrices(const OvCore::SceneSystem::Scene& p_scene, std::vector& p_out)
+std::vector OvCore::ECS::Renderer::FindLightMatrices(const OvCore::SceneSystem::Scene& p_scene)
{
+ std::vector result;
+
const auto& facs = p_scene.GetFastAccessComponents();
for (auto light : facs.lights)
+ {
if (light->owner.IsActive())
- p_out.push_back(light->GetData().GenerateMatrix());
+ {
+ result.push_back(light->GetData().GenerateMatrix());
+ }
+ }
+
+ return result;
}
-void OvCore::ECS::Renderer::RenderScene(OvCore::SceneSystem::Scene& p_scene, const OvMaths::FVector3& p_cameraPosition, Resources::Material* p_defaultMaterial)
+
+
+std::vector OvCore::ECS::Renderer::FindLightMatricesInFrustum(const OvCore::SceneSystem::Scene& p_scene, const OvRendering::Data::Frustum& p_frustum)
{
- OpaqueDrawables opaqueMeshes;
- TransparentDrawables transparentMeshes;
+ std::vector result;
+
+ const auto& facs = p_scene.GetFastAccessComponents();
- FindAndSortDrawables(opaqueMeshes, transparentMeshes, p_scene, p_cameraPosition, p_defaultMaterial);
+ for (auto light : facs.lights)
+ {
+ if (light->owner.IsActive())
+ {
+ const auto& lightData = light->GetData();
+ const auto& position = lightData.GetTransform().GetWorldPosition();
+ auto effectRange = lightData.GetEffectRange();
+
+ // We always consider lights that have an +inf range (Not necessary to test if they are in frustum)
+ if (std::isinf(effectRange) || p_frustum.SphereInFrustum(position.x, position.y, position.z, lightData.GetEffectRange()))
+ {
+ result.push_back(lightData.GenerateMatrix());
+ }
+ }
+ }
+
+ return result;
+}
+
+void OvCore::ECS::Renderer::RenderScene
+(
+ OvCore::SceneSystem::Scene& p_scene,
+ const OvMaths::FVector3& p_cameraPosition,
+ const OvRendering::LowRenderer::Camera& p_camera,
+ const OvRendering::Data::Frustum* p_customFrustum,
+ OvCore::Resources::Material* p_defaultMaterial
+)
+{
+ OpaqueDrawables opaqueMeshes;
+ TransparentDrawables transparentMeshes;
+
+ if (p_camera.HasFrustumGeometryCulling())
+ {
+ const auto& frustum = p_customFrustum ? *p_customFrustum : p_camera.GetFrustum();
+ std::tie(opaqueMeshes, transparentMeshes) = FindAndSortFrustumCulledDrawables(p_scene, p_cameraPosition, frustum, p_defaultMaterial);
+ }
+ else
+ {
+ std::tie(opaqueMeshes, transparentMeshes) = FindAndSortDrawables(p_scene, p_cameraPosition, p_defaultMaterial);
+ }
- for (const auto&[distance, drawable] : opaqueMeshes)
+ for (const auto& [distance, drawable] : opaqueMeshes)
DrawDrawable(drawable);
for (const auto& [distance, drawable] : transparentMeshes)
DrawDrawable(drawable);
}
-void OvCore::ECS::Renderer::FindAndSortDrawables(OpaqueDrawables& p_opaques, TransparentDrawables& p_transparents, const OvCore::SceneSystem::Scene& p_scene, const OvMaths::FVector3& p_cameraPosition, Resources::Material* p_defaultMaterial)
+void FindAndSortDrawables
+(
+ OvCore::ECS::Renderer::OpaqueDrawables& p_opaques,
+ OvCore::ECS::Renderer::TransparentDrawables& p_transparents,
+ const OvCore::SceneSystem::Scene& p_scene,
+ const OvMaths::FVector3& p_cameraPosition,
+ OvCore::Resources::Material* p_defaultMaterial
+)
{
for (OvCore::ECS::Components::CModelRenderer* modelRenderer : p_scene.GetFastAccessComponents().modelRenderers)
{
@@ -71,6 +131,8 @@ void OvCore::ECS::Renderer::FindAndSortDrawables(OpaqueDrawables& p_opaques, Tra
if (auto materialRenderer = modelRenderer->owner.GetComponent())
{
+ const auto& transform = modelRenderer->owner.transform.GetFTransform();
+
const OvCore::ECS::Components::CMaterialRenderer::MaterialList& materials = materialRenderer->GetMaterials();
for (auto mesh : model->GetMeshes())
@@ -86,7 +148,7 @@ void OvCore::ECS::Renderer::FindAndSortDrawables(OpaqueDrawables& p_opaques, Tra
if (material)
{
- Drawable element = { modelRenderer->owner.transform.GetWorldMatrix(), mesh, material, materialRenderer->GetUserMatrix() };
+ OvCore::ECS::Renderer::Drawable element = { transform.GetWorldMatrix(), mesh, material, materialRenderer->GetUserMatrix() };
if (material->IsBlendable())
p_transparents.emplace(distanceToActor, element);
@@ -100,6 +162,140 @@ void OvCore::ECS::Renderer::FindAndSortDrawables(OpaqueDrawables& p_opaques, Tra
}
}
+std::pair OvCore::ECS::Renderer::FindAndSortFrustumCulledDrawables
+(
+ const OvCore::SceneSystem::Scene& p_scene,
+ const OvMaths::FVector3& p_cameraPosition,
+ const OvRendering::Data::Frustum& p_frustum,
+ OvCore::Resources::Material* p_defaultMaterial
+)
+{
+ using namespace OvCore::ECS::Components;
+
+ OvCore::ECS::Renderer::OpaqueDrawables opaqueDrawables;
+ OvCore::ECS::Renderer::TransparentDrawables transparentDrawables;
+
+ for (CModelRenderer* modelRenderer : p_scene.GetFastAccessComponents().modelRenderers)
+ {
+ auto& owner = modelRenderer->owner;
+
+ if (owner.IsActive())
+ {
+ if (auto model = modelRenderer->GetModel())
+ {
+ if (auto materialRenderer = modelRenderer->owner.GetComponent())
+ {
+ auto& transform = owner.transform.GetFTransform();
+
+ OvRendering::Settings::ECullingOptions cullingOptions = OvRendering::Settings::ECullingOptions::NONE;
+
+ if (modelRenderer->GetFrustumBehaviour() != CModelRenderer::EFrustumBehaviour::DISABLED)
+ {
+ cullingOptions |= OvRendering::Settings::ECullingOptions::FRUSTUM_PER_MODEL;
+ }
+
+ if (modelRenderer->GetFrustumBehaviour() == CModelRenderer::EFrustumBehaviour::CULL_MESHES)
+ {
+ cullingOptions |= OvRendering::Settings::ECullingOptions::FRUSTUM_PER_MESH;
+ }
+
+ const auto& modelBoundingSphere = modelRenderer->GetFrustumBehaviour() == CModelRenderer::EFrustumBehaviour::CULL_CUSTOM ? modelRenderer->GetCustomBoundingSphere() : model->GetBoundingSphere();
+
+ std::vector> meshes;
+
+ {
+ PROFILER_SPY("Frustum Culling");
+ meshes = GetMeshesInFrustum(*model, modelBoundingSphere, transform, p_frustum, cullingOptions);
+ }
+
+ if (!meshes.empty())
+ {
+ float distanceToActor = OvMaths::FVector3::Distance(transform.GetWorldPosition(), p_cameraPosition);
+ const OvCore::ECS::Components::CMaterialRenderer::MaterialList& materials = materialRenderer->GetMaterials();
+
+ for (const auto& mesh : meshes)
+ {
+ OvCore::Resources::Material* material = nullptr;
+
+ if (mesh.get().GetMaterialIndex() < MAX_MATERIAL_COUNT)
+ {
+ material = materials.at(mesh.get().GetMaterialIndex());
+ if (!material || !material->GetShader())
+ material = p_defaultMaterial;
+ }
+
+ if (material)
+ {
+ OvCore::ECS::Renderer::Drawable element = { transform.GetWorldMatrix(), &mesh.get(), material, materialRenderer->GetUserMatrix() };
+
+ if (material->IsBlendable())
+ transparentDrawables.emplace(distanceToActor, element);
+ else
+ opaqueDrawables.emplace(distanceToActor, element);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return { opaqueDrawables, transparentDrawables };
+}
+
+std::pair OvCore::ECS::Renderer::FindAndSortDrawables
+(
+ const OvCore::SceneSystem::Scene& p_scene,
+ const OvMaths::FVector3& p_cameraPosition,
+ OvCore::Resources::Material* p_defaultMaterial
+)
+{
+ OvCore::ECS::Renderer::OpaqueDrawables opaqueDrawables;
+ OvCore::ECS::Renderer::TransparentDrawables transparentDrawables;
+
+ for (OvCore::ECS::Components::CModelRenderer* modelRenderer : p_scene.GetFastAccessComponents().modelRenderers)
+ {
+ if (modelRenderer->owner.IsActive())
+ {
+ if (auto model = modelRenderer->GetModel())
+ {
+ float distanceToActor = OvMaths::FVector3::Distance(modelRenderer->owner.transform.GetWorldPosition(), p_cameraPosition);
+
+ if (auto materialRenderer = modelRenderer->owner.GetComponent())
+ {
+ const auto& transform = modelRenderer->owner.transform.GetFTransform();
+
+ const OvCore::ECS::Components::CMaterialRenderer::MaterialList& materials = materialRenderer->GetMaterials();
+
+ for (auto mesh : model->GetMeshes())
+ {
+ OvCore::Resources::Material* material = nullptr;
+
+ if (mesh->GetMaterialIndex() < MAX_MATERIAL_COUNT)
+ {
+ material = materials.at(mesh->GetMaterialIndex());
+ if (!material || !material->GetShader())
+ material = p_defaultMaterial;
+ }
+
+ if (material)
+ {
+ OvCore::ECS::Renderer::Drawable element = { transform.GetWorldMatrix(), mesh, material, materialRenderer->GetUserMatrix() };
+
+ if (material->IsBlendable())
+ transparentDrawables.emplace(distanceToActor, element);
+ else
+ opaqueDrawables.emplace(distanceToActor, element);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return { opaqueDrawables, transparentDrawables };
+}
+
void OvCore::ECS::Renderer::DrawDrawable(const Drawable& p_toDraw)
{
m_userMatrixSender(std::get<3>(p_toDraw));
diff --git a/Sources/Overload/OvDebug/OvDebug.vcxproj b/Sources/Overload/OvDebug/OvDebug.vcxproj
index 7cc086e3..67bd14e6 100644
--- a/Sources/Overload/OvDebug/OvDebug.vcxproj
+++ b/Sources/Overload/OvDebug/OvDebug.vcxproj
@@ -14,19 +14,19 @@
15.0
{03A0CA9A-2BB6-4284-8D8E-F6F0F9E6DD32}
OvDebug
- 10.0.17763.0
+ 10.0
DynamicLibrary
true
- v141
+ v142
MultiByte
DynamicLibrary
false
- v141
+ v142
true
MultiByte
diff --git a/Sources/Overload/OvEditor/OvEditor.vcxproj b/Sources/Overload/OvEditor/OvEditor.vcxproj
index 8b7b7481..ce444ef2 100644
--- a/Sources/Overload/OvEditor/OvEditor.vcxproj
+++ b/Sources/Overload/OvEditor/OvEditor.vcxproj
@@ -14,19 +14,19 @@
15.0
{7EBB8C83-AB76-40FA-9F8F-8C2398AA3F7F}
OvEditor
- 10.0.17763.0
+ 10.0
Application
true
- v141
+ v142
MultiByte
Application
false
- v141
+ v142
true
MultiByte
@@ -48,6 +48,7 @@
$(ProjectDir)include\;$(SolutionDir)..\..\Build\OvCore\include\;$(IncludePath)
$(SolutionDir)..\..\Build\OvCore\lib\$(Configuration)\;$(LibraryPath)
$(ProjectDir)src\;$(SourcePath)
+ Overload
$(SolutionDir)..\..\Bin\$(ProjectName)\$(Configuration)\
@@ -55,6 +56,7 @@
$(ProjectDir)include\;$(SolutionDir)..\..\Build\OvCore\include\;$(IncludePath)
$(SolutionDir)..\..\Build\OvCore\lib\$(Configuration)\;$(LibraryPath)
$(ProjectDir)src\;$(SourcePath)
+ Overload
@@ -140,6 +142,7 @@ xcopy "$(ProjectDir)Layout.ini" "$(SolutionDir)..\..\Build\$(ProjectName)\$(Conf
+
@@ -160,6 +163,7 @@ xcopy "$(ProjectDir)Layout.ini" "$(SolutionDir)..\..\Build\$(ProjectName)\$(Conf
+
@@ -169,6 +173,7 @@ xcopy "$(ProjectDir)Layout.ini" "$(SolutionDir)..\..\Build\$(ProjectName)\$(Conf
+
@@ -190,6 +195,7 @@ xcopy "$(ProjectDir)Layout.ini" "$(SolutionDir)..\..\Build\$(ProjectName)\$(Conf
+
diff --git a/Sources/Overload/OvEditor/OvEditor.vcxproj.filters b/Sources/Overload/OvEditor/OvEditor.vcxproj.filters
index d05fa459..4f82f6ff 100644
--- a/Sources/Overload/OvEditor/OvEditor.vcxproj.filters
+++ b/Sources/Overload/OvEditor/OvEditor.vcxproj.filters
@@ -96,6 +96,12 @@
Source Files
+
+ Source Files
+
+
+ Source Files
+
@@ -182,6 +188,12 @@
Header Files
+
+ Header Files
+
+
+ Header Files
+
diff --git a/Sources/Overload/OvEditor/include/OvEditor/Core/CameraController.h b/Sources/Overload/OvEditor/include/OvEditor/Core/CameraController.h
index 97e480e8..90232798 100644
--- a/Sources/Overload/OvEditor/include/OvEditor/Core/CameraController.h
+++ b/Sources/Overload/OvEditor/include/OvEditor/Core/CameraController.h
@@ -78,6 +78,11 @@ namespace OvEditor::Core
*/
OvMaths::FVector3 GetPosition() const;
+ /**
+ * Returns true if the right mouse click is being pressed
+ */
+ bool IsRightMousePressed() const;
+
private:
void HandleCameraXYMovement(float p_deltaTime);
void HandleCameraZMovement(float p_deltaTime);
diff --git a/Sources/Overload/OvEditor/include/OvEditor/Core/EditorRenderer.h b/Sources/Overload/OvEditor/include/OvEditor/Core/EditorRenderer.h
index aa351412..525282f7 100644
--- a/Sources/Overload/OvEditor/include/OvEditor/Core/EditorRenderer.h
+++ b/Sources/Overload/OvEditor/include/OvEditor/Core/EditorRenderer.h
@@ -17,6 +17,7 @@
#include "OvEditor/Core/Context.h"
+namespace OvEditor::Core { enum class EGizmoOperation; }
namespace OvEditor::Panels { class AView; }
namespace OvEditor::Core
@@ -38,11 +39,29 @@ namespace OvEditor::Core
*/
void InitMaterials();
+ /**
+ * Prepare the picking material by send it the color corresponding to the given actor
+ * @param p_actor
+ */
+ void PreparePickingMaterial(OvCore::ECS::Actor& p_actor);
+
+ /**
+ * Calculate the model matrix for a camera attached to the given actor
+ * @param p_actor
+ */
+ OvMaths::FMatrix4 CalculateCameraModelMatrix(OvCore::ECS::Actor& p_actor);
+
/**
* Render the scene
* @param p_cameraPosition
+ * @param p_camera
+ */
+ void RenderScene(const OvMaths::FVector3& p_cameraPosition, const OvRendering::LowRenderer::Camera& p_camera, const OvRendering::Data::Frustum* p_customFrustum = nullptr);
+
+ /**
+ * Render the scene for actor picking (Unlit version of the scene with colors indicating actor IDs)
*/
- void RenderScene(const OvMaths::FVector3& p_cameraPosition);
+ void RenderSceneForActorPicking();
/**
* Render the User Interface
@@ -55,11 +74,13 @@ namespace OvEditor::Core
void RenderCameras();
/**
- * Render a guizmo at position
+ * Render a gizmo at position
* @param p_position
* @param p_rotation
+ * @param p_operation
+ * @param p_pickable (Determine the shader to use to render the gizmo)
*/
- void RenderGuizmo(const OvMaths::FVector3& p_position, const OvMaths::FQuaternion& p_rotation);
+ void RenderGizmo(const OvMaths::FVector3& p_position, const OvMaths::FQuaternion& p_rotation, OvEditor::Core::EGizmoOperation p_operation, bool p_pickable = false);
/**
* Render a model to the stencil buffer
@@ -78,11 +99,21 @@ namespace OvEditor::Core
*/
void RenderActorAsSelected(OvCore::ECS::Actor& p_actor, bool p_toStencil);
+ /**
+ * Render the camera frustum
+ */
+ void RenderCameraFrustum(OvCore::ECS::Components::CCamera& p_camera);
+
/**
* Render an actor collider
*/
void RenderActorCollider(OvCore::ECS::Actor& p_actor);
+ /**
+ * Render light bounds
+ */
+ void RenderLightBounds(OvCore::ECS::Components::CLight& p_light);
+
/**
* Render ambient box volume
*/
@@ -93,6 +124,11 @@ namespace OvEditor::Core
*/
void RenderAmbientSphereVolume(OvCore::ECS::Components::CAmbientSphereLight& p_ambientSphereLight);
+ /**
+ * Render the the bounding spheres of the given model renderer
+ */
+ void RenderBoundingSpheres(OvCore::ECS::Components::CModelRenderer& p_modelRenderer);
+
/**
* Render model
*/
@@ -119,6 +155,12 @@ namespace OvEditor::Core
*/
void UpdateLights(OvCore::SceneSystem::Scene& p_scene);
+ /**
+ * Update the light SSBO with the current scene (Lights outside of the given frustum are culled)
+ * @param p_scene
+ */
+ void UpdateLightsInFrustum(OvCore::SceneSystem::Scene& p_scene, const OvRendering::Data::Frustum& p_frustum);
+
private:
Context& m_context;
@@ -129,7 +171,9 @@ namespace OvEditor::Core
OvCore::Resources::Material m_emptyMaterial;
OvCore::Resources::Material m_defaultMaterial;
OvCore::Resources::Material m_cameraMaterial;
- OvCore::Resources::Material m_guizmoArrowMaterial;
- OvCore::Resources::Material m_guizmoBallMaterial;
+ OvCore::Resources::Material m_gizmoArrowMaterial;
+ OvCore::Resources::Material m_gizmoBallMaterial;
+ OvCore::Resources::Material m_gizmoPickingMaterial;
+ OvCore::Resources::Material m_actorPickingMaterial;
};
}
\ No newline at end of file
diff --git a/Sources/Overload/OvEditor/include/OvEditor/Core/GizmoBehaviour.h b/Sources/Overload/OvEditor/include/OvEditor/Core/GizmoBehaviour.h
new file mode 100644
index 00000000..2f38613c
--- /dev/null
+++ b/Sources/Overload/OvEditor/include/OvEditor/Core/GizmoBehaviour.h
@@ -0,0 +1,119 @@
+/**
+* @project: Overload
+* @author: Overload Tech.
+* @restrictions: This software may not be resold, redistributed or otherwise conveyed to a third party.
+*/
+
+#pragma once
+
+#include
+
+namespace OvEditor::Core
+{
+ enum class EGizmoOperation
+ {
+ TRANSLATE,
+ ROTATE,
+ SCALE
+ };
+
+ /* Handle gizmo behaviours */
+ class GizmoBehaviour
+ {
+ public:
+ enum class EDirection
+ {
+ X,
+ Y,
+ Z
+ };
+
+ /**
+ * Starts the gizmo picking behaviour for the given target in the given direction
+ * @param p_actor
+ * @param p_cameraPosition
+ * @param p_operation
+ * @param p_direction
+ */
+ void StartPicking(OvCore::ECS::Actor& p_target, const OvMaths::FVector3& p_cameraPosition, EGizmoOperation p_operation, EDirection p_direction);
+
+ /**
+ * Stops the gizmo picking behaviour
+ */
+ void StopPicking();
+
+ /**
+ * Handle the current behaviour
+ * @param p_viewMatrix
+ * @param p_projectionMatrix
+ * @param p_viewSize
+ */
+ void ApplyOperation(const OvMaths::FMatrix4& p_viewMatrix, const OvMaths::FMatrix4& p_projectionMatrix, const OvMaths::FVector2& p_viewSize);
+
+ /**
+ * Set the given mouse position as the current mouse position and update the previous mouse position
+ * @param p_mousePosition
+ */
+ void SetCurrentMouse(const OvMaths::FVector2& p_mousePosition);
+
+ /**
+ * Returns true if the gizmo is currently picked
+ */
+ bool IsPicking() const;
+
+ private:
+ /**
+ * Returns the global direction matching with the current m_direction
+ */
+ OvMaths::FVector3 GetFakeDirection() const;
+
+ /**
+ * Returns the actual direction of the target matching with the current m_direction
+ * @param p_relative (If true, the direction depends on hierarchy)
+ */
+ OvMaths::FVector3 GetRealDirection(bool p_relative = false) const;
+
+ /**
+ * Returns the 3D vector of the arrow projected to the screen
+ * @param p_viewMatrix
+ * @param p_projectionMatrix
+ * @param p_viewSize
+ */
+ OvMaths::FVector2 GetScreenDirection(const OvMaths::FMatrix4& p_viewMatrix, const OvMaths::FMatrix4& p_projectionMatrix, const OvMaths::FVector2& p_viewSize) const;
+
+ /**
+ * Handle the translation behaviour
+ * @param p_viewMatrix
+ * @param p_projectionMatrix
+ * @param p_viewSize
+ */
+ void ApplyTranslation(const OvMaths::FMatrix4& p_viewMatrix, const OvMaths::FMatrix4& p_projectionMatrix, const OvMaths::FVector2& p_viewSize) const;
+
+ /**
+ * Handle the rotation behaviour
+ * @param p_viewMatrix
+ * @param p_projectionMatrix
+ * @param p_viewSize
+ */
+ void ApplyRotation(const OvMaths::FMatrix4& p_viewMatrix, const OvMaths::FMatrix4& p_projectionMatrix, const OvMaths::FVector2& p_viewSize) const;
+
+ /**
+ * Handle the scale behaviour
+ * @param p_viewMatrix
+ * @param p_projectionMatrix
+ * @param p_viewSize
+ */
+ void ApplyScale(const OvMaths::FMatrix4& p_viewMatrix, const OvMaths::FMatrix4& p_projectionMatrix, const OvMaths::FVector2& p_viewSize) const;
+
+ private:
+ bool m_firstMouse = true;
+ float m_distanceToActor = 0.0f;
+ OvCore::ECS::Actor* m_target;
+ EGizmoOperation m_currentOperation;
+ EDirection m_direction;
+ OvMaths::FTransform m_originalTransform;
+ OvMaths::FVector2 m_originMouse;
+ OvMaths::FVector2 m_currentMouse;
+ OvMaths::FVector2 m_screenDirection;
+ };
+}
diff --git a/Sources/Overload/OvEditor/include/OvEditor/Core/ProjectHub.h b/Sources/Overload/OvEditor/include/OvEditor/Core/ProjectHub.h
index f68d534d..741f73dd 100644
--- a/Sources/Overload/OvEditor/include/OvEditor/Core/ProjectHub.h
+++ b/Sources/Overload/OvEditor/include/OvEditor/Core/ProjectHub.h
@@ -36,6 +36,12 @@ namespace OvEditor::Core
*/
void SetupContext();
+ /**
+ * Register the project (identified from the given path) into the project hub
+ * @param p_path
+ */
+ void RegisterProject(const std::string& p_path);
+
private:
std::unique_ptr m_device;
std::unique_ptr m_window;
diff --git a/Sources/Overload/OvEditor/include/OvEditor/Panels/AView.h b/Sources/Overload/OvEditor/include/OvEditor/Panels/AView.h
index 7afcc44e..6f13782b 100644
--- a/Sources/Overload/OvEditor/include/OvEditor/Panels/AView.h
+++ b/Sources/Overload/OvEditor/include/OvEditor/Panels/AView.h
@@ -10,6 +10,7 @@
#include
#include
#include
+#include
#include
namespace OvEditor::Core { class EditorRenderer; }
@@ -35,27 +36,12 @@ namespace OvEditor::Panels
const OvUI::Settings::PanelWindowSettings& p_windowSettings
);
- /**
- * Destructor
- */
- ~AView();
-
/**
* Update the view
* @param p_deltaTime
*/
virtual void Update(float p_deltaTime);
- /**
- * Bind the FBO attached to the view
- */
- void Bind();
-
- /**
- * Unbind the FBO attached to the view
- */
- void Unbind();
-
/**
* Custom implementation of the draw method
*/
@@ -108,6 +94,12 @@ namespace OvEditor::Panels
*/
void FillEngineUBO();
+ protected:
+ /**
+ * Update camera matrices
+ */
+ void PrepareCamera();
+
protected:
OvEditor::Core::EditorRenderer& m_editorRenderer;
OvRendering::LowRenderer::Camera m_camera;
@@ -116,9 +108,6 @@ namespace OvEditor::Panels
OvMaths::FVector3 m_gridColor = OvMaths::FVector3::One;
- private:
- uint32_t m_fbo;
- uint32_t m_renderTexture;
- uint32_t m_depthStencilBuffer;
+ OvRendering::Buffers::Framebuffer m_fbo;
};
}
\ No newline at end of file
diff --git a/Sources/Overload/OvEditor/include/OvEditor/Panels/AViewControllable.h b/Sources/Overload/OvEditor/include/OvEditor/Panels/AViewControllable.h
index 343685ec..effc4cfa 100644
--- a/Sources/Overload/OvEditor/include/OvEditor/Panels/AViewControllable.h
+++ b/Sources/Overload/OvEditor/include/OvEditor/Panels/AViewControllable.h
@@ -40,7 +40,7 @@ namespace OvEditor::Panels
*/
OvEditor::Core::CameraController& GetCameraController();
- private:
+ protected:
OvEditor::Core::CameraController m_cameraController;
};
}
\ No newline at end of file
diff --git a/Sources/Overload/OvEditor/include/OvEditor/Panels/GameView.h b/Sources/Overload/OvEditor/include/OvEditor/Panels/GameView.h
index c7fa56e8..bc79b8b2 100644
--- a/Sources/Overload/OvEditor/include/OvEditor/Panels/GameView.h
+++ b/Sources/Overload/OvEditor/include/OvEditor/Panels/GameView.h
@@ -41,6 +41,16 @@ namespace OvEditor::Panels
*/
virtual void _Render_Impl() override;
+ /**
+ * Returns true if the game view has a camera
+ */
+ bool HasCamera() const;
+
+ /**
+ * Returns the game view camera frustum or nothing if the game isn't playing
+ */
+ std::optional GetActiveFrustum() const;
+
private:
OvCore::SceneSystem::SceneManager& m_sceneManager;
bool m_hasCamera = false;
diff --git a/Sources/Overload/OvEditor/include/OvEditor/Panels/SceneView.h b/Sources/Overload/OvEditor/include/OvEditor/Panels/SceneView.h
index 0378f33b..0e1248ad 100644
--- a/Sources/Overload/OvEditor/include/OvEditor/Panels/SceneView.h
+++ b/Sources/Overload/OvEditor/include/OvEditor/Panels/SceneView.h
@@ -7,6 +7,7 @@
#pragma once
#include "OvEditor/Panels/AViewControllable.h"
+#include "OvEditor/Core/GizmoBehaviour.h"
namespace OvEditor::Panels
{
@@ -27,8 +28,7 @@ namespace OvEditor::Panels
);
/**
- * Update the scene view (Inputs logic)
- * @param p_deltaTime
+ * Update the scene view
*/
virtual void Update(float p_deltaTime) override;
@@ -37,7 +37,26 @@ namespace OvEditor::Panels
*/
virtual void _Render_Impl() override;
+ /**
+ * Render the actual scene
+ * @param p_defaultRenderState
+ */
+ void RenderScene(uint8_t p_defaultRenderState);
+
+ /**
+ * Render the scene for actor picking (Using unlit colors)
+ */
+ void RenderSceneForActorPicking();
+
+ /**
+ * Render the scene for actor picking and handle the logic behind it
+ */
+ void HandleActorPicking();
+
private:
OvCore::SceneSystem::SceneManager& m_sceneManager;
+ OvRendering::Buffers::Framebuffer m_actorPickingFramebuffer;
+ OvEditor::Core::GizmoBehaviour m_gizmoOperations;
+ OvEditor::Core::EGizmoOperation m_currentOperation = OvEditor::Core::EGizmoOperation::TRANSLATE;
};
}
\ No newline at end of file
diff --git a/Sources/Overload/OvEditor/include/OvEditor/Resources/RawShaders.h b/Sources/Overload/OvEditor/include/OvEditor/Resources/RawShaders.h
index 6c544899..fbc3ffcd 100644
--- a/Sources/Overload/OvEditor/include/OvEditor/Resources/RawShaders.h
+++ b/Sources/Overload/OvEditor/include/OvEditor/Resources/RawShaders.h
@@ -22,8 +22,8 @@ namespace OvEditor::Resources
static std::pair GetGrid();
/**
- * Retursn the guizmo shader
+ * Returns the gizmo shader
*/
- static std::pair GetGuizmo();
+ static std::pair GetGizmo();
};
}
\ No newline at end of file
diff --git a/Sources/Overload/OvEditor/include/OvEditor/Settings/EditorSettings.h b/Sources/Overload/OvEditor/include/OvEditor/Settings/EditorSettings.h
new file mode 100644
index 00000000..53768e02
--- /dev/null
+++ b/Sources/Overload/OvEditor/include/OvEditor/Settings/EditorSettings.h
@@ -0,0 +1,81 @@
+/**
+* @project: Overload
+* @author: Overload Tech.
+* @restrictions: This software may not be resold, redistributed or otherwise conveyed to a third party.
+*/
+
+#pragma once
+
+#include
+
+namespace OvEditor::Settings
+{
+ /**
+ * Accessible from anywhere editor settings
+ */
+ class EditorSettings
+ {
+ public:
+ template
+ class Property
+ {
+ public:
+ /**
+ * Creates the property with a default value
+ * @param p_value
+ */
+ Property(T p_value) : m_value(p_value) {}
+
+ /**
+ * Event called when the property value changes
+ */
+ OvTools::Eventing::Event OnValueChanged;
+
+ /**
+ * Assign a new value to the property
+ * @param p_value
+ */
+ inline T& operator=(T p_value)
+ {
+ Set(p_value);
+ return m_value;
+ }
+
+ /**
+ * Assign a new valeu to the property
+ * @param p_value
+ */
+ inline void Set(T p_value)
+ {
+ m_value = p_value;
+ OnValueChanged.Invoke(m_value);
+ }
+
+ inline operator T()
+ {
+ return m_value;
+ }
+
+ /**
+ * Returns the value of the property
+ */
+ inline T Get() const
+ {
+ return m_value;
+ }
+
+ private:
+ T m_value;
+ };
+
+ /**
+ * No construction possible
+ */
+ EditorSettings() = delete;
+
+ inline static Property ShowGeometryBounds = { false };
+ inline static Property ShowLightBounds = { false };
+ inline static Property ShowGeometryFrustumCullingInSceneView = { false };
+ inline static Property ShowLightFrustumCullingInSceneView = { false };
+ };
+}
diff --git a/Sources/Overload/OvEditor/src/OvEditor/Core/CameraController.cpp b/Sources/Overload/OvEditor/src/OvEditor/Core/CameraController.cpp
index 843f2c7e..460ef643 100644
--- a/Sources/Overload/OvEditor/src/OvEditor/Core/CameraController.cpp
+++ b/Sources/Overload/OvEditor/src/OvEditor/Core/CameraController.cpp
@@ -232,6 +232,11 @@ OvMaths::FVector3 OvEditor::Core::CameraController::GetPosition() const
return m_cameraPosition;
}
+bool OvEditor::Core::CameraController::IsRightMousePressed() const
+{
+ return m_rightMousePressed;
+}
+
void OvEditor::Core::CameraController::HandleCameraXYMovement(float p_deltaTime)
{
ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
diff --git a/Sources/Overload/OvEditor/src/OvEditor/Core/Context.cpp b/Sources/Overload/OvEditor/src/OvEditor/Core/Context.cpp
index 97a5321d..8986ffac 100644
--- a/Sources/Overload/OvEditor/src/OvEditor/Core/Context.cpp
+++ b/Sources/Overload/OvEditor/src/OvEditor/Core/Context.cpp
@@ -40,7 +40,7 @@ OvEditor::Core::Context::Context(const std::string& p_projectPath, const std::st
/* Settings */
OvWindowing::Settings::DeviceSettings deviceSettings;
deviceSettings.contextMajorVersion = 4;
- deviceSettings.contextMajorVersion = 3;
+ deviceSettings.contextMinorVersion = 3;
windowSettings.title = "Overload Editor";
windowSettings.width = 1280;
windowSettings.height = 720;
diff --git a/Sources/Overload/OvEditor/src/OvEditor/Core/Editor.cpp b/Sources/Overload/OvEditor/src/OvEditor/Core/Editor.cpp
index 58a74a20..950ffce7 100644
--- a/Sources/Overload/OvEditor/src/OvEditor/Core/Editor.cpp
+++ b/Sources/Overload/OvEditor/src/OvEditor/Core/Editor.cpp
@@ -82,8 +82,8 @@ void OvEditor::Core::Editor::PreUpdate()
void OvEditor::Core::Editor::Update(float p_deltaTime)
{
UpdateCurrentEditorMode(p_deltaTime);
- UpdateEditorPanels(p_deltaTime);
PrepareRendering(p_deltaTime);
+ UpdateEditorPanels(p_deltaTime);
RenderViews(p_deltaTime);
RenderEditorUI(p_deltaTime);
m_editorActions.ExecuteDelayedActions();
@@ -176,15 +176,8 @@ void OvEditor::Core::Editor::UpdateEditorPanels(float p_deltaTime)
void OvEditor::Core::Editor::PrepareRendering(float p_deltaTime)
{
- {
- PROFILER_SPY("Light SSBO Update");
- m_editorRenderer.UpdateLights(*m_context.sceneManager.GetCurrentScene());
- }
-
- {
- PROFILER_SPY("Engine UBO Update");
- m_context.engineUBO->SetSubData(m_context.device->GetElapsedTime(), 3 * sizeof(OvMaths::FMatrix4) + sizeof(OvMaths::FVector3));
- }
+ PROFILER_SPY("Engine UBO Update");
+ m_context.engineUBO->SetSubData(m_context.device->GetElapsedTime(), 3 * sizeof(OvMaths::FMatrix4) + sizeof(OvMaths::FVector3));
}
void OvEditor::Core::Editor::RenderViews(float p_deltaTime)
@@ -197,8 +190,8 @@ void OvEditor::Core::Editor::RenderViews(float p_deltaTime)
PROFILER_SPY("Editor Views Update");
assetView.Update(p_deltaTime);
- sceneView.Update(p_deltaTime);
gameView.Update(p_deltaTime);
+ sceneView.Update(p_deltaTime);
}
if (assetView.IsOpened())
@@ -212,13 +205,6 @@ void OvEditor::Core::Editor::RenderViews(float p_deltaTime)
m_context.lightSSBO->Bind(0);
- if (sceneView.IsOpened())
- {
- PROFILER_SPY("Scene View Rendering");
-
- sceneView.Render();
- }
-
if (gameView.IsOpened())
{
PROFILER_SPY("Game View Rendering");
@@ -226,6 +212,13 @@ void OvEditor::Core::Editor::RenderViews(float p_deltaTime)
gameView.Render();
}
+ if (sceneView.IsOpened())
+ {
+ PROFILER_SPY("Scene View Rendering");
+
+ sceneView.Render();
+ }
+
m_context.lightSSBO->Unbind();
}
diff --git a/Sources/Overload/OvEditor/src/OvEditor/Core/EditorRenderer.cpp b/Sources/Overload/OvEditor/src/OvEditor/Core/EditorRenderer.cpp
index ec3332b6..6ed8c242 100644
--- a/Sources/Overload/OvEditor/src/OvEditor/Core/EditorRenderer.cpp
+++ b/Sources/Overload/OvEditor/src/OvEditor/Core/EditorRenderer.cpp
@@ -13,9 +13,16 @@
#include
#include
+#include
+
+#include
+
#include "OvEditor/Core/EditorRenderer.h"
#include "OvEditor/Core/EditorResources.h"
#include "OvEditor/Panels/AView.h"
+#include "OvEditor/Panels/GameView.h"
+#include "OvEditor/Core/GizmoBehaviour.h"
+#include "OvEditor/Settings/EditorSettings.h"
#include "OvEditor/Core/EditorActions.h"
@@ -23,6 +30,11 @@ using namespace OvMaths;
using namespace OvRendering::Resources;
using namespace OvCore::Resources;
+const OvMaths::FVector3 DEBUG_BOUNDS_COLOR = { 1.0f, 0.0f, 0.0f };
+const OvMaths::FVector3 LIGHT_VOLUME_COLOR = { 1.0f, 1.0f, 0.0f };
+const OvMaths::FVector3 COLLIDER_COLOR = { 0.0f, 1.0f, 0.0f };
+const OvMaths::FVector3 FRUSTUM_COLOR = { 1.0f, 1.0f, 1.0f };
+
OvEditor::Core::EditorRenderer::EditorRenderer(Context& p_context) : m_context(p_context)
{
m_context.renderer->SetCapability(OvRendering::Settings::ERenderingCapability::STENCIL_TEST, true);
@@ -96,25 +108,121 @@ void OvEditor::Core::EditorRenderer::InitMaterials()
m_outlineMaterial.Set("u_DiffuseMap", nullptr);
m_outlineMaterial.SetDepthTest(false);
- /* Guizmo Arrow Material */
- m_guizmoArrowMaterial.SetShader(m_context.editorResources->GetShader("Guizmo"));
- m_guizmoArrowMaterial.SetGPUInstances(3);
- m_guizmoArrowMaterial.Set("u_IsBall", false);
+ /* Gizmo Arrow Material */
+ m_gizmoArrowMaterial.SetShader(m_context.editorResources->GetShader("Gizmo"));
+ m_gizmoArrowMaterial.SetGPUInstances(3);
+ m_gizmoArrowMaterial.Set("u_IsBall", false);
+ m_gizmoArrowMaterial.Set("u_IsPickable", false);
+
+ /* Gizmo Ball Material */
+ m_gizmoBallMaterial.SetShader(m_context.editorResources->GetShader("Gizmo"));
+ m_gizmoBallMaterial.Set("u_IsBall", true);
+ m_gizmoBallMaterial.Set("u_IsPickable", false);
+
+ /* Gizmo Pickable Material */
+ m_gizmoPickingMaterial.SetShader(m_context.editorResources->GetShader("Gizmo"));
+ m_gizmoPickingMaterial.SetGPUInstances(3);
+ m_gizmoPickingMaterial.Set("u_IsBall", false);
+ m_gizmoPickingMaterial.Set("u_IsPickable", true);
+
+ /* Picking Material */
+ m_actorPickingMaterial.SetShader(m_context.shaderManager[":Shaders\\Unlit.glsl"]);
+ m_actorPickingMaterial.Set("u_Diffuse", FVector4(1.f, 1.f, 1.f, 1.0f));
+ m_actorPickingMaterial.Set("u_DiffuseMap", nullptr);
+ m_actorPickingMaterial.SetFrontfaceCulling(false);
+ m_actorPickingMaterial.SetBackfaceCulling(false);
+}
+
+void OvEditor::Core::EditorRenderer::PreparePickingMaterial(OvCore::ECS::Actor& p_actor)
+{
+ uint32_t actorID = static_cast(p_actor.GetID());
+
+ auto bytes = reinterpret_cast(&actorID);
+ auto color = FVector4{ bytes[0] / 255.0f, bytes[1] / 255.0f, bytes[2] / 255.0f, 1.0f };
- /* Guizmo Ball Material */
- m_guizmoBallMaterial.SetShader(m_context.editorResources->GetShader("Guizmo"));
- m_guizmoBallMaterial.SetShader(m_context.editorResources->GetShader("Guizmo"));
- m_guizmoBallMaterial.Set("u_IsBall", true);
+ m_actorPickingMaterial.Set("u_Diffuse", color);
}
-void OvEditor::Core::EditorRenderer::RenderScene(const OvMaths::FVector3& p_cameraPosition)
+OvMaths::FMatrix4 OvEditor::Core::EditorRenderer::CalculateCameraModelMatrix(OvCore::ECS::Actor& p_actor)
+{
+ auto translation = FMatrix4::Translation(p_actor.transform.GetWorldPosition());
+ auto rotation = FQuaternion::ToMatrix4(p_actor.transform.GetWorldRotation());
+ auto scale = FMatrix4::Scaling({ 0.4f, 0.4f, 0.4f });
+
+ return translation * rotation * scale;
+}
+
+void OvEditor::Core::EditorRenderer::RenderScene(const OvMaths::FVector3& p_cameraPosition, const OvRendering::LowRenderer::Camera& p_camera, const OvRendering::Data::Frustum* p_customFrustum)
{
/* Render the actors */
m_context.lightSSBO->Bind(0);
- m_context.renderer->RenderScene(*m_context.sceneManager.GetCurrentScene(), p_cameraPosition, &m_emptyMaterial);
+ m_context.renderer->RenderScene(*m_context.sceneManager.GetCurrentScene(), p_cameraPosition, p_camera, p_customFrustum, &m_emptyMaterial);
m_context.lightSSBO->Unbind();
}
+void OvEditor::Core::EditorRenderer::RenderSceneForActorPicking()
+{
+ auto& scene = *m_context.sceneManager.GetCurrentScene();
+
+ /* Render models */
+ for (auto modelRenderer : scene.GetFastAccessComponents().modelRenderers)
+ {
+ auto& actor = modelRenderer->owner;
+
+ if (actor.IsActive())
+ {
+ if (auto model = modelRenderer->GetModel())
+ {
+ if (auto materialRenderer = modelRenderer->owner.GetComponent())
+ {
+ const OvCore::ECS::Components::CMaterialRenderer::MaterialList& materials = materialRenderer->GetMaterials();
+ const auto& modelMatrix = actor.transform.GetWorldMatrix();
+
+ PreparePickingMaterial(actor);
+
+ for (auto mesh : model->GetMeshes())
+ {
+ OvCore::Resources::Material* material = nullptr;
+
+ if (mesh->GetMaterialIndex() < MAX_MATERIAL_COUNT)
+ {
+ material = materials.at(mesh->GetMaterialIndex());
+ if (!material || !material->GetShader())
+ material = &m_emptyMaterial;
+ }
+
+ if (material)
+ {
+ m_actorPickingMaterial.SetBackfaceCulling(material->HasBackfaceCulling());
+ m_actorPickingMaterial.SetFrontfaceCulling(material->HasFrontfaceCulling());
+ m_actorPickingMaterial.SetColorWriting(material->HasColorWriting());
+ m_actorPickingMaterial.SetDepthTest(material->HasDepthTest());
+ m_actorPickingMaterial.SetDepthWriting(material->HasDepthWriting());
+
+ m_context.renderer->DrawMesh(*mesh, m_actorPickingMaterial, &modelMatrix);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* Render cameras */
+ for (auto camera : m_context.sceneManager.GetCurrentScene()->GetFastAccessComponents().cameras)
+ {
+ auto& actor = camera->owner;
+
+ if (actor.IsActive())
+ {
+ PreparePickingMaterial(actor);
+ auto& model = *m_context.editorResources->GetModel("Camera");
+ auto modelMatrix = CalculateCameraModelMatrix(actor);
+
+ m_context.renderer->DrawModelWithSingleMaterial(model, m_actorPickingMaterial, &modelMatrix);
+ }
+ }
+}
+
void OvEditor::Core::EditorRenderer::RenderUI()
{
m_context.uiManager->Render();
@@ -122,24 +230,53 @@ void OvEditor::Core::EditorRenderer::RenderUI()
void OvEditor::Core::EditorRenderer::RenderCameras()
{
+ using namespace OvMaths;
+
for (auto camera : m_context.sceneManager.GetCurrentScene()->GetFastAccessComponents().cameras)
{
- if (camera->owner.IsActive())
+ auto& actor = camera->owner;
+
+ if (actor.IsActive())
{
- auto modelMatrix = FMatrix4::Translation(camera->owner.transform.GetWorldPosition()) * FQuaternion::ToMatrix4(camera->owner.transform.GetWorldRotation()) * FMatrix4::Scaling({ 0.4f, 0.4f, 0.4f });
- m_context.renderer->DrawModelWithSingleMaterial(*m_context.editorResources->GetModel("Camera"), m_cameraMaterial, &modelMatrix);
+ auto& model = *m_context.editorResources->GetModel("Camera");
+ auto modelMatrix = CalculateCameraModelMatrix(actor);
+
+ m_context.renderer->DrawModelWithSingleMaterial(model, m_cameraMaterial, &modelMatrix);
}
}
}
-void OvEditor::Core::EditorRenderer::RenderGuizmo(const OvMaths::FVector3& p_position, const OvMaths::FQuaternion& p_rotation)
+void OvEditor::Core::EditorRenderer::RenderGizmo(const OvMaths::FVector3& p_position, const OvMaths::FQuaternion& p_rotation, OvEditor::Core::EGizmoOperation p_operation, bool p_pickable)
{
using namespace OvMaths;
FMatrix4 model = FMatrix4::Translation(p_position) * FQuaternion::ToMatrix4(FQuaternion::Normalize(p_rotation));
- FMatrix4 sphereModel = model * OvMaths::FMatrix4::Scaling({ 0.1f, 0.1f, 0.1f });
- m_context.renderer->DrawModelWithSingleMaterial(*m_context.editorResources->GetModel("Sphere"), m_guizmoBallMaterial, &sphereModel);
- m_context.renderer->DrawModelWithSingleMaterial(*m_context.editorResources->GetModel("Arrow"), m_guizmoArrowMaterial, &model);
+
+ if (!p_pickable)
+ {
+ FMatrix4 sphereModel = model * OvMaths::FMatrix4::Scaling({ 0.1f, 0.1f, 0.1f });
+ m_context.renderer->DrawModelWithSingleMaterial(*m_context.editorResources->GetModel("Sphere"), m_gizmoBallMaterial, &sphereModel);
+ }
+
+ OvRendering::Resources::Model* arrowModel = nullptr;
+
+ switch (p_operation)
+ {
+ case OvEditor::Core::EGizmoOperation::TRANSLATE:
+ arrowModel = m_context.editorResources->GetModel("Arrow_Translate");
+ break;
+ case OvEditor::Core::EGizmoOperation::ROTATE:
+ arrowModel = m_context.editorResources->GetModel("Arrow_Rotate");
+ break;
+ case OvEditor::Core::EGizmoOperation::SCALE:
+ arrowModel = m_context.editorResources->GetModel("Arrow_Scale");
+ break;
+ }
+
+ if (arrowModel)
+ {
+ m_context.renderer->DrawModelWithSingleMaterial(*arrowModel, p_pickable ? m_gizmoPickingMaterial : m_gizmoArrowMaterial, &model);
+ }
}
void OvEditor::Core::EditorRenderer::RenderModelToStencil(const OvMaths::FMatrix4& p_worldMatrix, OvRendering::Resources::Model& p_model)
@@ -164,13 +301,18 @@ void OvEditor::Core::EditorRenderer::RenderActorAsSelected(OvCore::ECS::Actor& p
{
if (p_actor.IsActive())
{
- /* Render static mesh outline */
+ /* Render static mesh outline and bounding spheres */
if (auto modelRenderer = p_actor.GetComponent(); modelRenderer && modelRenderer->GetModel())
{
if (p_toStencil)
RenderModelToStencil(p_actor.transform.GetWorldMatrix(), *modelRenderer->GetModel());
else
RenderModelOutline(p_actor.transform.GetWorldMatrix(), *modelRenderer->GetModel());
+
+ if (Settings::EditorSettings::ShowGeometryBounds)
+ {
+ RenderBoundingSpheres(*modelRenderer);
+ }
}
/* Render camera component outline */
@@ -182,6 +324,8 @@ void OvEditor::Core::EditorRenderer::RenderActorAsSelected(OvCore::ECS::Actor& p
RenderModelToStencil(model, *m_context.editorResources->GetModel("Camera"));
else
RenderModelOutline(model, *m_context.editorResources->GetModel("Camera"));
+
+ RenderCameraFrustum(*cameraComponent);
}
/* Render the actor collider */
@@ -201,11 +345,88 @@ void OvEditor::Core::EditorRenderer::RenderActorAsSelected(OvCore::ECS::Actor& p
RenderAmbientSphereVolume(*ambientSphereComp);
}
+ if (OvEditor::Settings::EditorSettings::ShowLightBounds)
+ {
+ if (auto light = p_actor.GetComponent(); light && !p_toStencil)
+ {
+ RenderLightBounds(*light);
+ }
+ }
+
for (auto& child : p_actor.GetChildren())
RenderActorAsSelected(*child, p_toStencil);
}
}
+void OvEditor::Core::EditorRenderer::RenderCameraFrustum(OvCore::ECS::Components::CCamera& p_camera)
+{
+ auto& gameView = EDITOR_PANEL(Panels::GameView, "Game View");
+ auto gameViewSize = gameView.GetSafeSize();
+
+ if (gameViewSize.first == 0 || gameViewSize.second == 0)
+ {
+ gameViewSize = { 16, 9 };
+ }
+
+ auto& owner = p_camera.owner;
+ auto& camera = p_camera.GetCamera();
+
+ const auto& cameraPos = owner.transform.GetWorldPosition();
+ const auto& cameraForward = owner.transform.GetWorldForward();
+ const auto& cameraRotation = owner.transform.GetWorldRotation();
+
+ auto drawFrustumLine = [&](const FVector3& p_start, const FVector3& p_end, float planeDistance)
+ {
+ auto offset = cameraPos + cameraForward * planeDistance;
+ auto start = offset + p_start;
+ auto end = offset + p_end;
+ m_context.shapeDrawer->DrawLine(start, end, FRUSTUM_COLOR);
+ };
+
+ camera.CacheMatrices(gameViewSize.first, gameViewSize.second, cameraPos);
+ const auto proj = FMatrix4::Transpose(camera.GetProjectionMatrix());
+ const auto near = camera.GetNear();
+ const auto far = camera.GetFar();
+
+ const auto nLeft = near * (proj.data[2] - 1.0f) / proj.data[0];
+ const auto nRight = near * (1.0f + proj.data[2]) / proj.data[0];
+ const auto nTop = near * (1.0f + proj.data[6]) / proj.data[5];
+ const auto nBottom = near * (proj.data[6] - 1.0f) / proj.data[5];
+
+ // Get the sides of the far plane.
+ const auto fLeft = far * (proj.data[2] - 1.0f) / proj.data[0];
+ const auto fRight = far * (1.0f + proj.data[2]) / proj.data[0];
+ const auto fTop = far * (1.0f + proj.data[6]) / proj.data[5];
+ const auto fBottom = far * (proj.data[6] - 1.0f) / proj.data[5];
+
+ auto a = cameraRotation * FVector3{ nLeft, nTop, 0 };
+ auto b = cameraRotation * FVector3{ nRight, nTop, 0 };
+ auto c = cameraRotation * FVector3{ nLeft, nBottom, 0 };
+ auto d = cameraRotation * FVector3{ nRight, nBottom, 0 };
+ auto e = cameraRotation * FVector3{ fLeft, fTop, 0 };
+ auto f = cameraRotation * FVector3{ fRight, fTop, 0 };
+ auto g = cameraRotation * FVector3{ fLeft, fBottom, 0 };
+ auto h = cameraRotation * FVector3{ fRight, fBottom, 0 };
+
+ // Draw near plane
+ drawFrustumLine(a, b, near);
+ drawFrustumLine(b, d, near);
+ drawFrustumLine(d, c, near);
+ drawFrustumLine(c, a, near);
+
+ // Draw far plane
+ drawFrustumLine(e, f, far);
+ drawFrustumLine(f, h, far);
+ drawFrustumLine(h, g, far);
+ drawFrustumLine(g, e, far);
+
+ // Draw lines between near and far planes
+ drawFrustumLine(a + cameraForward * near, e + cameraForward * far, 0);
+ drawFrustumLine(b + cameraForward * near, f + cameraForward * far, 0);
+ drawFrustumLine(c + cameraForward * near, g + cameraForward * far, 0);
+ drawFrustumLine(d + cameraForward * near, h + cameraForward * far, 0);
+}
+
void OvEditor::Core::EditorRenderer::RenderActorCollider(OvCore::ECS::Actor & p_actor)
{
using namespace OvCore::ECS::Components;
@@ -293,6 +514,30 @@ void OvEditor::Core::EditorRenderer::RenderActorCollider(OvCore::ECS::Actor & p_
m_context.renderer->SetRasterizationLinesWidth(1.0f);
}
+void OvEditor::Core::EditorRenderer::RenderLightBounds(OvCore::ECS::Components::CLight& p_light)
+{
+ bool depthTestBackup = m_context.renderer->GetCapability(OvRendering::Settings::ERenderingCapability::DEPTH_TEST);
+ m_context.renderer->SetCapability(OvRendering::Settings::ERenderingCapability::DEPTH_TEST, false);
+
+ auto& data = p_light.GetData();
+
+ OvMaths::FQuaternion rotation = data.GetTransform().GetWorldRotation();
+ OvMaths::FVector3 center = data.GetTransform().GetWorldPosition();
+ float radius = data.GetEffectRange();
+
+ if (!std::isinf(radius))
+ {
+ for (float i = 0; i <= 360.0f; i += 10.0f)
+ {
+ m_context.shapeDrawer->DrawLine(center + rotation * (OvMaths::FVector3{ cos(i * (3.14f / 180.0f)), sin(i * (3.14f / 180.0f)), 0.f } *radius), center + rotation * (OvMaths::FVector3{ cos((i + 10.0f) * (3.14f / 180.0f)), sin((i + 10.0f) * (3.14f / 180.0f)), 0.f } *radius), DEBUG_BOUNDS_COLOR, 1.f);
+ m_context.shapeDrawer->DrawLine(center + rotation * (OvMaths::FVector3{ 0.f, sin(i * (3.14f / 180.0f)), cos(i * (3.14f / 180.0f)) } *radius), center + rotation * (OvMaths::FVector3{ 0.f, sin((i + 10.0f) * (3.14f / 180.0f)), cos((i + 10.0f) * (3.14f / 180.0f)) } *radius), DEBUG_BOUNDS_COLOR, 1.f);
+ m_context.shapeDrawer->DrawLine(center + rotation * (OvMaths::FVector3{ cos(i * (3.14f / 180.0f)), 0.f, sin(i * (3.14f / 180.0f)) } *radius), center + rotation * (OvMaths::FVector3{ cos((i + 10.0f) * (3.14f / 180.0f)), 0.f, sin((i + 10.0f) * (3.14f / 180.0f)) } *radius), DEBUG_BOUNDS_COLOR, 1.f);
+ }
+ }
+
+ m_context.renderer->SetCapability(OvRendering::Settings::ERenderingCapability::DEPTH_TEST, depthTestBackup);
+}
+
void OvEditor::Core::EditorRenderer::RenderAmbientBoxVolume(OvCore::ECS::Components::CAmbientBoxLight & p_ambientBoxLight)
{
bool depthTestBackup = m_context.renderer->GetCapability(OvRendering::Settings::ERenderingCapability::DEPTH_TEST);
@@ -309,18 +554,18 @@ void OvEditor::Core::EditorRenderer::RenderAmbientBoxVolume(OvCore::ECS::Compone
OvMaths::FVector3 actorScale = p_ambientBoxLight.owner.transform.GetWorldScale();
OvMaths::FVector3 halfSize = size / 2.f;
- m_context.shapeDrawer->DrawLine(center + OvMaths::FVector3{ -halfSize.x, -halfSize.y, -halfSize.z }, center + OvMaths::FVector3{ -halfSize.x, -halfSize.y, +halfSize.z }, OvMaths::FVector3{ 1.f, 1.f, 0.f }, 1.f);
- m_context.shapeDrawer->DrawLine(center + OvMaths::FVector3{ -halfSize.x, halfSize.y, -halfSize.z }, center + OvMaths::FVector3{ -halfSize.x, +halfSize.y, +halfSize.z }, OvMaths::FVector3{ 1.f, 1.f, 0.f }, 1.f);
- m_context.shapeDrawer->DrawLine(center + OvMaths::FVector3{ -halfSize.x, -halfSize.y, -halfSize.z }, center + OvMaths::FVector3{ -halfSize.x, +halfSize.y, -halfSize.z }, OvMaths::FVector3{ 1.f, 1.f, 0.f }, 1.f);
- m_context.shapeDrawer->DrawLine(center + OvMaths::FVector3{ -halfSize.x, -halfSize.y, +halfSize.z }, center + OvMaths::FVector3{ -halfSize.x, +halfSize.y, +halfSize.z }, OvMaths::FVector3{ 1.f, 1.f, 0.f }, 1.f);
- m_context.shapeDrawer->DrawLine(center + OvMaths::FVector3{ +halfSize.x, -halfSize.y, -halfSize.z }, center + OvMaths::FVector3{ +halfSize.x, -halfSize.y, +halfSize.z }, OvMaths::FVector3{ 1.f, 1.f, 0.f }, 1.f);
- m_context.shapeDrawer->DrawLine(center + OvMaths::FVector3{ +halfSize.x, halfSize.y, -halfSize.z }, center + OvMaths::FVector3{ +halfSize.x, +halfSize.y, +halfSize.z }, OvMaths::FVector3{ 1.f, 1.f, 0.f }, 1.f);
- m_context.shapeDrawer->DrawLine(center + OvMaths::FVector3{ +halfSize.x, -halfSize.y, -halfSize.z }, center + OvMaths::FVector3{ +halfSize.x, +halfSize.y, -halfSize.z }, OvMaths::FVector3{ 1.f, 1.f, 0.f }, 1.f);
- m_context.shapeDrawer->DrawLine(center + OvMaths::FVector3{ +halfSize.x, -halfSize.y, +halfSize.z }, center + OvMaths::FVector3{ +halfSize.x, +halfSize.y, +halfSize.z }, OvMaths::FVector3{ 1.f, 1.f, 0.f }, 1.f);
- m_context.shapeDrawer->DrawLine(center + OvMaths::FVector3{ -halfSize.x, -halfSize.y, -halfSize.z }, center + OvMaths::FVector3{ +halfSize.x, -halfSize.y, -halfSize.z }, OvMaths::FVector3{ 1.f, 1.f, 0.f }, 1.f);
- m_context.shapeDrawer->DrawLine(center + OvMaths::FVector3{ -halfSize.x, +halfSize.y, -halfSize.z }, center + OvMaths::FVector3{ +halfSize.x, +halfSize.y, -halfSize.z }, OvMaths::FVector3{ 1.f, 1.f, 0.f }, 1.f);
- m_context.shapeDrawer->DrawLine(center + OvMaths::FVector3{ -halfSize.x, -halfSize.y, +halfSize.z }, center + OvMaths::FVector3{ +halfSize.x, -halfSize.y, +halfSize.z }, OvMaths::FVector3{ 1.f, 1.f, 0.f }, 1.f);
- m_context.shapeDrawer->DrawLine(center + OvMaths::FVector3{ -halfSize.x, +halfSize.y, +halfSize.z }, center + OvMaths::FVector3{ +halfSize.x, +halfSize.y, +halfSize.z }, OvMaths::FVector3{ 1.f, 1.f, 0.f }, 1.f);
+ m_context.shapeDrawer->DrawLine(center + OvMaths::FVector3{ -halfSize.x, -halfSize.y, -halfSize.z }, center + OvMaths::FVector3{ -halfSize.x, -halfSize.y, +halfSize.z }, LIGHT_VOLUME_COLOR, 1.f);
+ m_context.shapeDrawer->DrawLine(center + OvMaths::FVector3{ -halfSize.x, halfSize.y, -halfSize.z }, center + OvMaths::FVector3{ -halfSize.x, +halfSize.y, +halfSize.z }, LIGHT_VOLUME_COLOR, 1.f);
+ m_context.shapeDrawer->DrawLine(center + OvMaths::FVector3{ -halfSize.x, -halfSize.y, -halfSize.z }, center + OvMaths::FVector3{ -halfSize.x, +halfSize.y, -halfSize.z }, LIGHT_VOLUME_COLOR, 1.f);
+ m_context.shapeDrawer->DrawLine(center + OvMaths::FVector3{ -halfSize.x, -halfSize.y, +halfSize.z }, center + OvMaths::FVector3{ -halfSize.x, +halfSize.y, +halfSize.z }, LIGHT_VOLUME_COLOR, 1.f);
+ m_context.shapeDrawer->DrawLine(center + OvMaths::FVector3{ +halfSize.x, -halfSize.y, -halfSize.z }, center + OvMaths::FVector3{ +halfSize.x, -halfSize.y, +halfSize.z }, LIGHT_VOLUME_COLOR, 1.f);
+ m_context.shapeDrawer->DrawLine(center + OvMaths::FVector3{ +halfSize.x, halfSize.y, -halfSize.z }, center + OvMaths::FVector3{ +halfSize.x, +halfSize.y, +halfSize.z }, LIGHT_VOLUME_COLOR, 1.f);
+ m_context.shapeDrawer->DrawLine(center + OvMaths::FVector3{ +halfSize.x, -halfSize.y, -halfSize.z }, center + OvMaths::FVector3{ +halfSize.x, +halfSize.y, -halfSize.z }, LIGHT_VOLUME_COLOR, 1.f);
+ m_context.shapeDrawer->DrawLine(center + OvMaths::FVector3{ +halfSize.x, -halfSize.y, +halfSize.z }, center + OvMaths::FVector3{ +halfSize.x, +halfSize.y, +halfSize.z }, LIGHT_VOLUME_COLOR, 1.f);
+ m_context.shapeDrawer->DrawLine(center + OvMaths::FVector3{ -halfSize.x, -halfSize.y, -halfSize.z }, center + OvMaths::FVector3{ +halfSize.x, -halfSize.y, -halfSize.z }, LIGHT_VOLUME_COLOR, 1.f);
+ m_context.shapeDrawer->DrawLine(center + OvMaths::FVector3{ -halfSize.x, +halfSize.y, -halfSize.z }, center + OvMaths::FVector3{ +halfSize.x, +halfSize.y, -halfSize.z }, LIGHT_VOLUME_COLOR, 1.f);
+ m_context.shapeDrawer->DrawLine(center + OvMaths::FVector3{ -halfSize.x, -halfSize.y, +halfSize.z }, center + OvMaths::FVector3{ +halfSize.x, -halfSize.y, +halfSize.z }, LIGHT_VOLUME_COLOR, 1.f);
+ m_context.shapeDrawer->DrawLine(center + OvMaths::FVector3{ -halfSize.x, +halfSize.y, +halfSize.z }, center + OvMaths::FVector3{ +halfSize.x, +halfSize.y, +halfSize.z }, LIGHT_VOLUME_COLOR, 1.f);
m_context.renderer->SetCapability(OvRendering::Settings::ERenderingCapability::DEPTH_TEST, depthTestBackup);
}
@@ -338,12 +583,76 @@ void OvEditor::Core::EditorRenderer::RenderAmbientSphereVolume(OvCore::ECS::Comp
for (float i = 0; i <= 360.0f; i += 10.0f)
{
- m_context.shapeDrawer->DrawLine(center + rotation * (OvMaths::FVector3{ cos(i * (3.14f / 180.0f)), sin(i * (3.14f / 180.0f)), 0.f } *radius), center + rotation * (OvMaths::FVector3{ cos((i + 10.0f) * (3.14f / 180.0f)), sin((i + 10.0f) * (3.14f / 180.0f)), 0.f } *radius), OvMaths::FVector3{ 1.f, 1.f, 0.f }, 1.f);
- m_context.shapeDrawer->DrawLine(center + rotation * (OvMaths::FVector3{ 0.f, sin(i * (3.14f / 180.0f)), cos(i * (3.14f / 180.0f)) } *radius), center + rotation * (OvMaths::FVector3{ 0.f, sin((i + 10.0f) * (3.14f / 180.0f)), cos((i + 10.0f) * (3.14f / 180.0f)) } *radius), OvMaths::FVector3{ 1.f, 1.f, 0.f }, 1.f);
- m_context.shapeDrawer->DrawLine(center + rotation * (OvMaths::FVector3{ cos(i * (3.14f / 180.0f)), 0.f, sin(i * (3.14f / 180.0f)) } *radius), center + rotation * (OvMaths::FVector3{ cos((i + 10.0f) * (3.14f / 180.0f)), 0.f, sin((i + 10.0f) * (3.14f / 180.0f)) } *radius), OvMaths::FVector3{ 1.f, 1.f, 0.f }, 1.f);
+ m_context.shapeDrawer->DrawLine(center + rotation * (OvMaths::FVector3{ cos(i * (3.14f / 180.0f)), sin(i * (3.14f / 180.0f)), 0.f } *radius), center + rotation * (OvMaths::FVector3{ cos((i + 10.0f) * (3.14f / 180.0f)), sin((i + 10.0f) * (3.14f / 180.0f)), 0.f } *radius), LIGHT_VOLUME_COLOR, 1.f);
+ m_context.shapeDrawer->DrawLine(center + rotation * (OvMaths::FVector3{ 0.f, sin(i * (3.14f / 180.0f)), cos(i * (3.14f / 180.0f)) } *radius), center + rotation * (OvMaths::FVector3{ 0.f, sin((i + 10.0f) * (3.14f / 180.0f)), cos((i + 10.0f) * (3.14f / 180.0f)) } *radius), LIGHT_VOLUME_COLOR, 1.f);
+ m_context.shapeDrawer->DrawLine(center + rotation * (OvMaths::FVector3{ cos(i * (3.14f / 180.0f)), 0.f, sin(i * (3.14f / 180.0f)) } *radius), center + rotation * (OvMaths::FVector3{ cos((i + 10.0f) * (3.14f / 180.0f)), 0.f, sin((i + 10.0f) * (3.14f / 180.0f)) } *radius), LIGHT_VOLUME_COLOR, 1.f);
+ }
+
+ m_context.renderer->SetCapability(OvRendering::Settings::ERenderingCapability::DEPTH_TEST, depthTestBackup);
+}
+
+void OvEditor::Core::EditorRenderer::RenderBoundingSpheres(OvCore::ECS::Components::CModelRenderer& p_modelRenderer)
+{
+ using namespace OvCore::ECS::Components;
+ using namespace OvPhysics::Entities;
+
+ bool depthTestBackup = m_context.renderer->GetCapability(OvRendering::Settings::ERenderingCapability::DEPTH_TEST);
+ m_context.renderer->SetCapability(OvRendering::Settings::ERenderingCapability::DEPTH_TEST, false);
+
+ /* Draw the sphere collider if any */
+ if (auto model = p_modelRenderer.GetModel())
+ {
+ auto& actor = p_modelRenderer.owner;
+
+ OvMaths::FVector3 actorScale = actor.transform.GetWorldScale();
+ OvMaths::FQuaternion actorRotation = actor.transform.GetWorldRotation();
+ OvMaths::FVector3 actorPosition = actor.transform.GetWorldPosition();
+
+ const auto& modelBoundingsphere =
+ p_modelRenderer.GetFrustumBehaviour() == OvCore::ECS::Components::CModelRenderer::EFrustumBehaviour::CULL_CUSTOM ?
+ p_modelRenderer.GetCustomBoundingSphere() :
+ model->GetBoundingSphere();
+
+ float radiusScale = std::max(std::max(std::max(actorScale.x, actorScale.y), actorScale.z), 0.0f);
+ float scaledRadius = modelBoundingsphere.radius * radiusScale;
+ auto sphereOffset = OvMaths::FQuaternion::RotatePoint(modelBoundingsphere.position, actorRotation) * radiusScale;
+
+ OvMaths::FVector3 boundingSphereCenter = actorPosition + sphereOffset;
+
+ for (float i = 0; i <= 360.0f; i += 10.0f)
+ {
+ m_context.shapeDrawer->DrawLine(boundingSphereCenter + actorRotation * (OvMaths::FVector3{ cos(i * (3.14f / 180.0f)), sin(i * (3.14f / 180.0f)), 0.f } *scaledRadius), boundingSphereCenter + actorRotation * (OvMaths::FVector3{ cos((i + 10.0f) * (3.14f / 180.0f)), sin((i + 10.0f) * (3.14f / 180.0f)), 0.f } *scaledRadius), DEBUG_BOUNDS_COLOR, 1.f);
+ m_context.shapeDrawer->DrawLine(boundingSphereCenter + actorRotation * (OvMaths::FVector3{ 0.f, sin(i * (3.14f / 180.0f)), cos(i * (3.14f / 180.0f)) } *scaledRadius), boundingSphereCenter + actorRotation * (OvMaths::FVector3{ 0.f, sin((i + 10.0f) * (3.14f / 180.0f)), cos((i + 10.0f) * (3.14f / 180.0f)) } *scaledRadius), DEBUG_BOUNDS_COLOR, 1.f);
+ m_context.shapeDrawer->DrawLine(boundingSphereCenter + actorRotation * (OvMaths::FVector3{ cos(i * (3.14f / 180.0f)), 0.f, sin(i * (3.14f / 180.0f)) } *scaledRadius), boundingSphereCenter + actorRotation * (OvMaths::FVector3{ cos((i + 10.0f) * (3.14f / 180.0f)), 0.f, sin((i + 10.0f) * (3.14f / 180.0f)) } *scaledRadius), DEBUG_BOUNDS_COLOR, 1.f);
+ }
+
+ if (p_modelRenderer.GetFrustumBehaviour() == OvCore::ECS::Components::CModelRenderer::EFrustumBehaviour::CULL_MESHES)
+ {
+ const auto& meshes = model->GetMeshes();
+
+ if (meshes.size() > 1) // One mesh would result into the same bounding sphere for mesh and model
+ {
+ for (auto mesh : meshes)
+ {
+ auto& meshBoundingSphere = mesh->GetBoundingSphere();
+ float scaledRadius = meshBoundingSphere.radius * radiusScale;
+ auto sphereOffset = OvMaths::FQuaternion::RotatePoint(meshBoundingSphere.position, actorRotation) * radiusScale;
+
+ OvMaths::FVector3 boundingSphereCenter = actorPosition + sphereOffset;
+
+ for (float i = 0; i <= 360.0f; i += 10.0f)
+ {
+ m_context.shapeDrawer->DrawLine(boundingSphereCenter + actorRotation * (OvMaths::FVector3{ cos(i * (3.14f / 180.0f)), sin(i * (3.14f / 180.0f)), 0.f } *scaledRadius), boundingSphereCenter + actorRotation * (OvMaths::FVector3{ cos((i + 10.0f) * (3.14f / 180.0f)), sin((i + 10.0f) * (3.14f / 180.0f)), 0.f } *scaledRadius), DEBUG_BOUNDS_COLOR, 1.f);
+ m_context.shapeDrawer->DrawLine(boundingSphereCenter + actorRotation * (OvMaths::FVector3{ 0.f, sin(i * (3.14f / 180.0f)), cos(i * (3.14f / 180.0f)) } *scaledRadius), boundingSphereCenter + actorRotation * (OvMaths::FVector3{ 0.f, sin((i + 10.0f) * (3.14f / 180.0f)), cos((i + 10.0f) * (3.14f / 180.0f)) } *scaledRadius), DEBUG_BOUNDS_COLOR, 1.f);
+ m_context.shapeDrawer->DrawLine(boundingSphereCenter + actorRotation * (OvMaths::FVector3{ cos(i * (3.14f / 180.0f)), 0.f, sin(i * (3.14f / 180.0f)) } *scaledRadius), boundingSphereCenter + actorRotation * (OvMaths::FVector3{ cos((i + 10.0f) * (3.14f / 180.0f)), 0.f, sin((i + 10.0f) * (3.14f / 180.0f)) } *scaledRadius), DEBUG_BOUNDS_COLOR, 1.f);
+ }
+ }
+ }
+ }
}
m_context.renderer->SetCapability(OvRendering::Settings::ERenderingCapability::DEPTH_TEST, depthTestBackup);
+ m_context.renderer->SetRasterizationLinesWidth(1.0f);
}
void OvEditor::Core::EditorRenderer::RenderModelAsset(OvRendering::Resources::Model& p_model)
@@ -371,13 +680,18 @@ void OvEditor::Core::EditorRenderer::RenderGrid(const OvMaths::FVector3& p_viewP
FMatrix4 model = FMatrix4::Scaling({ 1000.f, 1.f, 1000.f });
m_gridMaterial.Set("u_Color", p_color);
m_context.renderer->DrawModelWithSingleMaterial(*m_context.editorResources->GetModel("Plane"), m_gridMaterial, &model);
-
- // m_context.shapeDrawer->DrawGrid(p_viewPos, p_color, 1000, 0.1f, 0.5f, 20.0f, 1.0f);
}
void OvEditor::Core::EditorRenderer::UpdateLights(OvCore::SceneSystem::Scene& p_scene)
{
- std::vector lightMatrices;
- m_context.renderer->FindLightMatrices(p_scene, lightMatrices);
+ PROFILER_SPY("Light SSBO Update");
+ auto lightMatrices = m_context.renderer->FindLightMatrices(p_scene);
m_context.lightSSBO->SendBlocks(lightMatrices.data(), lightMatrices.size() * sizeof(FMatrix4));
-}
\ No newline at end of file
+}
+
+void OvEditor::Core::EditorRenderer::UpdateLightsInFrustum(OvCore::SceneSystem::Scene& p_scene, const OvRendering::Data::Frustum& p_frustum)
+{
+ PROFILER_SPY("Light SSBO Update (Frustum culled)");
+ auto lightMatrices = m_context.renderer->FindLightMatricesInFrustum(p_scene, p_frustum);
+ m_context.lightSSBO->SendBlocks(lightMatrices.data(), lightMatrices.size() * sizeof(FMatrix4));
+}
diff --git a/Sources/Overload/OvEditor/src/OvEditor/Core/EditorResources.cpp b/Sources/Overload/OvEditor/src/OvEditor/Core/EditorResources.cpp
index ddd4633d..7ac1d200 100644
--- a/Sources/Overload/OvEditor/src/OvEditor/Core/EditorResources.cpp
+++ b/Sources/Overload/OvEditor/src/OvEditor/Core/EditorResources.cpp
@@ -120,19 +120,21 @@ OvEditor::Core::EditorResources::EditorResources(const std::string& p_editorAsse
}
/* Models */
- m_models["Cube"] = ModelLoader::Create(modelsFolder + "Cube.fbx", modelParserFlags);
- m_models["Cylinder"] = ModelLoader::Create(modelsFolder + "Cylinder.fbx", modelParserFlags);
- m_models["Plane"] = ModelLoader::Create(modelsFolder + "Plane.fbx", modelParserFlags);
- m_models["Roll"] = ModelLoader::Create(modelsFolder + "Roll.fbx", modelParserFlags);
- m_models["Sphere"] = ModelLoader::Create(modelsFolder + "Sphere.fbx", modelParserFlags);
- m_models["Arrow"] = ModelLoader::Create(modelsFolder + "Arrow.fbx", modelParserFlags);
- m_models["Camera"] = ModelLoader::Create(modelsFolder + "Camera.fbx", modelParserFlags);
+ m_models["Cube"] = ModelLoader::Create(modelsFolder + "Cube.fbx", modelParserFlags);
+ m_models["Cylinder"] = ModelLoader::Create(modelsFolder + "Cylinder.fbx", modelParserFlags);
+ m_models["Plane"] = ModelLoader::Create(modelsFolder + "Plane.fbx", modelParserFlags);
+ m_models["Roll"] = ModelLoader::Create(modelsFolder + "Roll.fbx", modelParserFlags);
+ m_models["Sphere"] = ModelLoader::Create(modelsFolder + "Sphere.fbx", modelParserFlags);
+ m_models["Arrow_Translate"] = ModelLoader::Create(modelsFolder + "Arrow_Translate.fbx", modelParserFlags);
+ m_models["Arrow_Rotate"] = ModelLoader::Create(modelsFolder + "Arrow_Rotate.fbx", modelParserFlags);
+ m_models["Arrow_Scale"] = ModelLoader::Create(modelsFolder + "Arrow_Scale.fbx", modelParserFlags);
+ m_models["Camera"] = ModelLoader::Create(modelsFolder + "Camera.fbx", modelParserFlags);
/* Shaders */
auto gridSource = OvEditor::Resources::RawShaders::GetGrid();
- auto guizmoSource = OvEditor::Resources::RawShaders::GetGuizmo();
+ auto gizmoSource = OvEditor::Resources::RawShaders::GetGizmo();
m_shaders["Grid"] = ShaderLoader::CreateFromSource(gridSource.first, gridSource.second);
- m_shaders["Guizmo"] = ShaderLoader::CreateFromSource(guizmoSource.first, guizmoSource.second);
+ m_shaders["Gizmo"] = ShaderLoader::CreateFromSource(gizmoSource.first, gizmoSource.second);
/* From memory */
{
diff --git a/Sources/Overload/OvEditor/src/OvEditor/Core/GizmoBehaviour.cpp b/Sources/Overload/OvEditor/src/OvEditor/Core/GizmoBehaviour.cpp
new file mode 100644
index 00000000..bd5458ae
--- /dev/null
+++ b/Sources/Overload/OvEditor/src/OvEditor/Core/GizmoBehaviour.cpp
@@ -0,0 +1,178 @@
+/**
+* @project: Overload
+* @author: Overload Tech.
+* @restrictions: This software may not be resold, redistributed or otherwise conveyed to a third party.
+*/
+
+#include "OvEditor/Core/GizmoBehaviour.h"
+
+void OvEditor::Core::GizmoBehaviour::StartPicking(OvCore::ECS::Actor& p_target, const OvMaths::FVector3& p_cameraPosition, EGizmoOperation p_operation, EDirection p_direction)
+{
+ m_target = &p_target;
+ m_firstMouse = true;
+ m_originalTransform = p_target.transform.GetFTransform();
+ m_distanceToActor = OvMaths::FVector3::Distance(p_cameraPosition, m_target->transform.GetWorldPosition());
+ m_currentOperation = p_operation;
+ m_direction = p_direction;
+}
+
+void OvEditor::Core::GizmoBehaviour::StopPicking()
+{
+ m_target = nullptr;
+}
+
+OvMaths::FVector3 OvEditor::Core::GizmoBehaviour::GetFakeDirection() const
+{
+ auto result = OvMaths::FVector3();
+
+ switch (m_direction)
+ {
+ case OvEditor::Core::GizmoBehaviour::EDirection::X:
+ result = OvMaths::FVector3::Right;
+ break;
+ case OvEditor::Core::GizmoBehaviour::EDirection::Y:
+ result = OvMaths::FVector3::Up;
+ break;
+ case OvEditor::Core::GizmoBehaviour::EDirection::Z:
+ result = OvMaths::FVector3::Forward;
+ break;
+ }
+
+ return result;
+}
+
+OvMaths::FVector3 OvEditor::Core::GizmoBehaviour::GetRealDirection(bool p_relative) const
+{
+ auto result = OvMaths::FVector3();
+
+ switch (m_direction)
+ {
+ case OvEditor::Core::GizmoBehaviour::EDirection::X:
+ result = p_relative ? m_originalTransform.GetWorldRight() : m_originalTransform.GetLocalRight();
+ break;
+ case OvEditor::Core::GizmoBehaviour::EDirection::Y:
+ result = p_relative ? m_originalTransform.GetWorldUp() : m_originalTransform.GetLocalUp();
+ break;
+ case OvEditor::Core::GizmoBehaviour::EDirection::Z:
+ result = p_relative ? m_originalTransform.GetWorldForward() : m_originalTransform.GetLocalForward();
+ break;
+ }
+
+ return result;
+}
+
+OvMaths::FVector2 OvEditor::Core::GizmoBehaviour::GetScreenDirection(const OvMaths::FMatrix4& p_viewMatrix, const OvMaths::FMatrix4& p_projectionMatrix, const OvMaths::FVector2& p_viewSize) const
+{
+ auto start = m_originalTransform.GetWorldPosition();
+ auto end = m_originalTransform.GetWorldPosition() + GetRealDirection(true) * 0.01f;
+
+ auto start2D = OvMaths::FVector2();
+ {
+ auto clipSpacePos = p_projectionMatrix * (p_viewMatrix * OvMaths::FVector4{ start.x, start.y, start.z, 1.0f });
+ auto ndcSpacePos = OvMaths::FVector3{ clipSpacePos.x, clipSpacePos.y, clipSpacePos.z } / clipSpacePos.w;
+ auto windowSpacePos = ((OvMaths::FVector2{ ndcSpacePos.x, ndcSpacePos.y } + 1.0f) / 2.0f);
+ windowSpacePos.x *= p_viewSize.x;
+ windowSpacePos.y *= p_viewSize.y;
+ start2D = windowSpacePos;
+ }
+
+ auto end2D = OvMaths::FVector2();
+ {
+ auto clipSpacePos = p_projectionMatrix * (p_viewMatrix * OvMaths::FVector4{ end.x, end.y, end.z, 1.0f });
+ auto ndcSpacePos = OvMaths::FVector3{ clipSpacePos.x, clipSpacePos.y, clipSpacePos.z } / clipSpacePos.w;
+ auto windowSpacePos = ((OvMaths::FVector2{ ndcSpacePos.x, ndcSpacePos.y } + 1.0f) / 2.0f);
+ windowSpacePos.x *= p_viewSize.x;
+ windowSpacePos.y *= p_viewSize.y;
+ end2D = windowSpacePos;
+ }
+
+ auto result = end2D - start2D;
+
+ result.y *= -1; // Screen coordinates are reversed, so we inverse the Y
+
+ return OvMaths::FVector2::Normalize(result);
+}
+
+void OvEditor::Core::GizmoBehaviour::ApplyTranslation(const OvMaths::FMatrix4& p_viewMatrix, const OvMaths::FMatrix4& p_projectionMatrix, const OvMaths::FVector2& p_viewSize) const
+{
+ auto unitsPerPixel = 0.001f * m_distanceToActor;
+ auto originPosition = m_originalTransform.GetLocalPosition();
+
+ auto screenDirection = GetScreenDirection(p_viewMatrix, p_projectionMatrix, p_viewSize);
+
+ auto totalDisplacement = m_currentMouse - m_originMouse;
+ auto translationCoefficient = OvMaths::FVector2::Dot(totalDisplacement, screenDirection);
+
+ m_target->transform.SetLocalPosition(originPosition + GetRealDirection() * translationCoefficient * unitsPerPixel);
+}
+
+void OvEditor::Core::GizmoBehaviour::ApplyRotation(const OvMaths::FMatrix4& p_viewMatrix, const OvMaths::FMatrix4& p_projectionMatrix, const OvMaths::FVector2& p_viewSize) const
+{
+ auto unitsPerPixel = 0.2f;
+ auto originRotation = m_originalTransform.GetLocalRotation();
+
+ auto screenDirection = GetScreenDirection(p_viewMatrix, p_projectionMatrix, p_viewSize);
+ screenDirection = OvMaths::FVector2(-screenDirection.y, screenDirection.x);
+
+ auto totalDisplacement = m_currentMouse - m_originMouse;
+ auto rotationCoefficient = OvMaths::FVector2::Dot(totalDisplacement, screenDirection);
+
+ auto rotationToApply = OvMaths::FQuaternion(OvMaths::FVector3(GetFakeDirection() * rotationCoefficient * unitsPerPixel));
+ m_target->transform.SetLocalRotation(originRotation * rotationToApply);
+}
+
+void OvEditor::Core::GizmoBehaviour::ApplyScale(const OvMaths::FMatrix4& p_viewMatrix, const OvMaths::FMatrix4& p_projectionMatrix, const OvMaths::FVector2& p_viewSize) const
+{
+ auto unitsPerPixel = 0.01f;
+ auto originScale = m_originalTransform.GetLocalScale();
+
+ auto screenDirection = GetScreenDirection(p_viewMatrix, p_projectionMatrix, p_viewSize);
+
+ auto totalDisplacement = m_currentMouse - m_originMouse;
+ auto scaleCoefficient = OvMaths::FVector2::Dot(totalDisplacement, screenDirection);
+
+ auto newScale = originScale + GetFakeDirection() * scaleCoefficient * unitsPerPixel;
+
+ /* Prevent scale from being negative*/
+ newScale.x = std::max(newScale.x, 0.0001f);
+ newScale.y = std::max(newScale.y, 0.0001f);
+ newScale.z = std::max(newScale.z, 0.0001f);
+
+ m_target->transform.SetLocalScale(newScale);
+}
+
+void OvEditor::Core::GizmoBehaviour::ApplyOperation(const OvMaths::FMatrix4& p_viewMatrix, const OvMaths::FMatrix4& p_projectionMatrix, const OvMaths::FVector2& p_viewSize)
+{
+ switch (m_currentOperation)
+ {
+ case EGizmoOperation::TRANSLATE:
+ ApplyTranslation(p_viewMatrix, p_projectionMatrix, p_viewSize);
+ break;
+
+ case EGizmoOperation::ROTATE:
+ ApplyRotation(p_viewMatrix, p_projectionMatrix, p_viewSize);
+ break;
+
+ case EGizmoOperation::SCALE:
+ ApplyScale(p_viewMatrix, p_projectionMatrix, p_viewSize);
+ break;
+ }
+}
+
+void OvEditor::Core::GizmoBehaviour::SetCurrentMouse(const OvMaths::FVector2& p_mousePosition)
+{
+ if (m_firstMouse)
+ {
+ m_currentMouse = m_originMouse = p_mousePosition;
+ m_firstMouse = false;
+ }
+ else
+ {
+ m_currentMouse = p_mousePosition;
+ }
+}
+
+bool OvEditor::Core::GizmoBehaviour::IsPicking() const
+{
+ return m_target;
+}
\ No newline at end of file
diff --git a/Sources/Overload/OvEditor/src/OvEditor/Core/ProjectHub.cpp b/Sources/Overload/OvEditor/src/OvEditor/Core/ProjectHub.cpp
index 2e6b4e77..16d6df04 100644
--- a/Sources/Overload/OvEditor/src/OvEditor/Core/ProjectHub.cpp
+++ b/Sources/Overload/OvEditor/src/OvEditor/Core/ProjectHub.cpp
@@ -307,3 +307,8 @@ void OvEditor::Core::ProjectHub::SetupContext()
m_uiManager->EnableEditorLayoutSave(false);
m_uiManager->EnableDocking(false);
}
+
+void OvEditor::Core::ProjectHub::RegisterProject(const std::string& p_path)
+{
+ static_cast(m_mainPanel.get())->RegisterProject(p_path);
+}
diff --git a/Sources/Overload/OvEditor/src/OvEditor/Main.cpp b/Sources/Overload/OvEditor/src/OvEditor/Main.cpp
index 242e20a4..af0be930 100644
--- a/Sources/Overload/OvEditor/src/OvEditor/Main.cpp
+++ b/Sources/Overload/OvEditor/src/OvEditor/Main.cpp
@@ -4,20 +4,70 @@
* @restrictions: This software may not be resold, redistributed or otherwise conveyed to a third party.
*/
+#include
+
+#include
+
#include "OvEditor/Core/ProjectHub.h"
#include "OvEditor/Core/Application.h"
-#ifdef _DEBUG
- int main()
-#else
- #undef APIENTRY
- #include "Windows.h"
- INT WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, INT nCmdShow)
+#undef APIENTRY
+#include "Windows.h"
+
+/**
+* When Overload is launched from a project file, we should consider the executable path as
+* the current working directory
+* @param p_executablePath
+*/
+void UpdateWorkingDirectory(const std::string& p_executablePath)
+{
+ if (!IsDebuggerPresent())
+ {
+ std::filesystem::current_path(OvTools::Utils::PathParser::GetContainingFolder(p_executablePath));
+ }
+}
+
+int main(int argc, char** argv);
+
+#ifndef _DEBUG
+INT WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, INT nCmdShow)
+{
+ main(__argc, __argv);
+}
#endif
+
+int main(int argc, char** argv)
{
- OvEditor::Core::ProjectHub* hub = new OvEditor::Core::ProjectHub();
- auto[ready, projectPath, projectName] = hub->Run();
- delete hub;
+ UpdateWorkingDirectory(argv[0]);
+
+ bool ready = false;
+ std::string projectPath;
+ std::string projectName;
+
+ {
+ OvEditor::Core::ProjectHub hub;
+
+ if (argc < 2)
+ {
+ // No project file given as argument ==> Open the ProjectHub
+ std::tie(ready, projectPath, projectName) = hub.Run();
+ }
+ else
+ {
+ // Project file given as argument ==> Open the project
+ std::string projectFile = argv[1];
+
+ if (OvTools::Utils::PathParser::GetExtension(projectFile) == "ovproject")
+ {
+ ready = true;
+ projectPath = OvTools::Utils::PathParser::GetContainingFolder(projectFile);
+ projectName = OvTools::Utils::PathParser::GetElementName(projectFile);
+ OvTools::Utils::String::Replace(projectName, ".ovproject", "");
+ }
+
+ hub.RegisterProject(projectPath);
+ }
+ }
if (ready)
{
diff --git a/Sources/Overload/OvEditor/src/OvEditor/Panels/AView.cpp b/Sources/Overload/OvEditor/src/OvEditor/Panels/AView.cpp
index dc67c138..6b61a86d 100644
--- a/Sources/Overload/OvEditor/src/OvEditor/Panels/AView.cpp
+++ b/Sources/Overload/OvEditor/src/OvEditor/Panels/AView.cpp
@@ -16,62 +16,20 @@ OvEditor::Panels::AView::AView
const OvUI::Settings::PanelWindowSettings& p_windowSettings
) : PanelWindow(p_title, p_opened, p_windowSettings), m_editorRenderer(EDITOR_RENDERER())
{
- glGenFramebuffers(1, &m_fbo);
- glGenTextures(1, &m_renderTexture);
- glGenRenderbuffers(1, &m_depthStencilBuffer);
-
m_cameraPosition = { -10.0f, 4.0f, 10.0f };
m_camera.SetPitch(-10.0f);
m_camera.SetYaw(-45.f);
- m_image = &CreateWidget(m_renderTexture, OvMaths::FVector2{ 0.f, 0.f });
-}
-
-OvEditor::Panels::AView::~AView()
-{
- glDeleteBuffers(1, &m_fbo);
- glDeleteTextures(1, &m_renderTexture);
- glGenRenderbuffers(1, &m_depthStencilBuffer);
+ m_image = &CreateWidget(m_fbo.GetTextureID(), OvMaths::FVector2{ 0.f, 0.f });
}
void OvEditor::Panels::AView::Update(float p_deltaTime)
{
- Bind();
-
auto[winWidth, winHeight] = GetSafeSize();
m_image->size = OvMaths::FVector2(static_cast(winWidth), static_cast(winHeight));
- /* Setup texture */
- glBindTexture(GL_TEXTURE_2D, m_renderTexture);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, winWidth, winHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-
- /* Setup depth-stencil buffer (24 + 8 bits) */
- glBindRenderbuffer(GL_RENDERBUFFER, m_depthStencilBuffer);
- glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, winWidth, winHeight);
-
- /* Setup frame buffer */
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer);
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer);
- glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_renderTexture, 0);
-
- Unbind();
-}
-
-void OvEditor::Panels::AView::Bind()
-{
- auto[winWidth, winHeight] = GetSafeSize();
-
- glViewport(0, 0, winWidth, winHeight);
-
- glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
-}
-
-void OvEditor::Panels::AView::Unbind()
-{
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ m_fbo.Resize(winWidth, winHeight);
}
void OvEditor::Panels::AView::_Draw_Impl()
@@ -88,13 +46,12 @@ void OvEditor::Panels::AView::Render()
FillEngineUBO();
auto [winWidth, winHeight] = GetSafeSize();
- auto projection = m_camera.GetProjectionMatrix(winWidth, winHeight);
- auto view = m_camera.GetViewMatrix(m_cameraPosition);
- EDITOR_CONTEXT(shapeDrawer)->SetViewProjection(projection * view);
- Bind();
+ EDITOR_CONTEXT(shapeDrawer)->SetViewProjection(m_camera.GetProjectionMatrix() * m_camera.GetViewMatrix());
+
+ glViewport(0, 0, winWidth, winHeight); // TODO: Move this OpenGL call to OvRendering
+
_Render_Impl();
- Unbind();
}
void OvEditor::Panels::AView::SetCameraPosition(const OvMaths::FVector3 & p_position)
@@ -135,8 +92,14 @@ void OvEditor::Panels::AView::FillEngineUBO()
auto[winWidth, winHeight] = GetSafeSize();
size_t offset = sizeof(OvMaths::FMatrix4); // We skip the model matrix (Which is a special case, modified every draw calls)
- engineUBO.SetSubData(OvMaths::FMatrix4::Transpose(m_camera.GetViewMatrix(m_cameraPosition)), std::ref(offset));
- engineUBO.SetSubData(OvMaths::FMatrix4::Transpose(m_camera.GetProjectionMatrix(winWidth, winHeight)), std::ref(offset));
+ engineUBO.SetSubData(OvMaths::FMatrix4::Transpose(m_camera.GetViewMatrix()), std::ref(offset));
+ engineUBO.SetSubData(OvMaths::FMatrix4::Transpose(m_camera.GetProjectionMatrix()), std::ref(offset));
engineUBO.SetSubData(m_cameraPosition, std::ref(offset));
}
+void OvEditor::Panels::AView::PrepareCamera()
+{
+ auto [winWidth, winHeight] = GetSafeSize();
+ m_camera.CacheMatrices(winWidth, winHeight, m_cameraPosition);
+}
+
diff --git a/Sources/Overload/OvEditor/src/OvEditor/Panels/AssetBrowser.cpp b/Sources/Overload/OvEditor/src/OvEditor/Panels/AssetBrowser.cpp
index afff5396..15d9d12b 100644
--- a/Sources/Overload/OvEditor/src/OvEditor/Panels/AssetBrowser.cpp
+++ b/Sources/Overload/OvEditor/src/OvEditor/Panels/AssetBrowser.cpp
@@ -873,6 +873,32 @@ OvEditor::Panels::AssetBrowser::AssetBrowser
m_projectAssetFolder(p_projectAssetFolder),
m_projectScriptFolder(p_projectScriptFolder)
{
+ if (!std::filesystem::exists(m_projectAssetFolder))
+ {
+ std::filesystem::create_directories(m_projectAssetFolder);
+
+ OvWindowing::Dialogs::MessageBox message
+ (
+ "Assets folder not found",
+ "The \"Assets/\" folders hasn't been found in your project directory.\nIt has been automatically generated",
+ OvWindowing::Dialogs::MessageBox::EMessageType::WARNING,
+ OvWindowing::Dialogs::MessageBox::EButtonLayout::OK
+ );
+ }
+
+ if (!std::filesystem::exists(m_projectScriptFolder))
+ {
+ std::filesystem::create_directories(m_projectScriptFolder);
+
+ OvWindowing::Dialogs::MessageBox message
+ (
+ "Scripts folder not found",
+ "The \"Scripts/\" folders hasn't been found in your project directory.\nIt has been automatically generated",
+ OvWindowing::Dialogs::MessageBox::EMessageType::WARNING,
+ OvWindowing::Dialogs::MessageBox::EButtonLayout::OK
+ );
+ }
+
auto& refreshButton = CreateWidget("Rescan assets");
refreshButton.ClickedEvent += std::bind(&AssetBrowser::Refresh, this);
refreshButton.lineBreak = false;
diff --git a/Sources/Overload/OvEditor/src/OvEditor/Panels/AssetView.cpp b/Sources/Overload/OvEditor/src/OvEditor/Panels/AssetView.cpp
index 50a114b7..1e6b995f 100644
--- a/Sources/Overload/OvEditor/src/OvEditor/Panels/AssetView.cpp
+++ b/Sources/Overload/OvEditor/src/OvEditor/Panels/AssetView.cpp
@@ -20,6 +20,7 @@ OvEditor::Panels::AssetView::AssetView
) : AViewControllable(p_title, p_opened, p_windowSettings)
{
m_camera.SetClearColor({ 0.278f, 0.278f, 0.278f });
+ m_camera.SetFar(1000.0f);
m_resource = static_cast(nullptr);
m_image->AddPlugin>>("File").DataReceivedEvent += [this](auto p_data)
@@ -47,12 +48,18 @@ OvEditor::Panels::AssetView::AssetView
void OvEditor::Panels::AssetView::_Render_Impl()
{
- EDITOR_CONTEXT(renderer)->SetStencilMask(0xFF);
- EDITOR_CONTEXT(renderer)->Clear(m_camera);
- EDITOR_CONTEXT(renderer)->SetStencilMask(0x00);
+ PrepareCamera();
- uint8_t glState = EDITOR_CONTEXT(renderer)->FetchGLState();
- EDITOR_CONTEXT(renderer)->ApplyStateMask(glState);
+ auto& baseRenderer = *EDITOR_CONTEXT(renderer).get();
+
+ m_fbo.Bind();
+
+ baseRenderer.SetStencilMask(0xFF);
+ baseRenderer.Clear(m_camera);
+ baseRenderer.SetStencilMask(0x00);
+
+ uint8_t glState = baseRenderer.FetchGLState();
+ baseRenderer.ApplyStateMask(glState);
m_editorRenderer.RenderGrid(m_cameraPosition, m_gridColor);
@@ -65,7 +72,9 @@ void OvEditor::Panels::AssetView::_Render_Impl()
if (auto pval = std::get_if(&m_resource); pval && *pval)
m_editorRenderer.RenderMaterialAsset(**pval);
- EDITOR_CONTEXT(renderer)->ApplyStateMask(glState);
+ baseRenderer.ApplyStateMask(glState);
+
+ m_fbo.Unbind();
}
void OvEditor::Panels::AssetView::SetResource(ViewableResource p_resource)
diff --git a/Sources/Overload/OvEditor/src/OvEditor/Panels/GameView.cpp b/Sources/Overload/OvEditor/src/OvEditor/Panels/GameView.cpp
index b612f8d2..fe06ba57 100644
--- a/Sources/Overload/OvEditor/src/OvEditor/Panels/GameView.cpp
+++ b/Sources/Overload/OvEditor/src/OvEditor/Panels/GameView.cpp
@@ -9,6 +9,7 @@
#include "OvEditor/Core/EditorRenderer.h"
#include "OvEditor/Panels/GameView.h"
#include "OvEditor/Core/EditorActions.h"
+#include "OvEditor/Settings/EditorSettings.h"
OvEditor::Panels::GameView::GameView
(
@@ -33,6 +34,7 @@ void OvEditor::Panels::GameView::Update(float p_deltaTime)
m_camera = cameraComponent->GetCamera();
m_cameraPosition = cameraComponent->owner.transform.GetWorldPosition();
m_hasCamera = true;
+ PrepareCamera();
}
else
{
@@ -44,13 +46,41 @@ void OvEditor::Panels::GameView::Update(float p_deltaTime)
void OvEditor::Panels::GameView::_Render_Impl()
{
- EDITOR_CONTEXT(renderer)->Clear(m_camera);
+ auto& baseRenderer = *EDITOR_CONTEXT(renderer).get();
+ auto& currentScene = *m_sceneManager.GetCurrentScene();
- uint8_t glState = EDITOR_CONTEXT(renderer)->FetchGLState();
- EDITOR_CONTEXT(renderer)->ApplyStateMask(glState);
+ m_fbo.Bind();
+
+ baseRenderer.Clear(m_camera);
+
+ uint8_t glState = baseRenderer.FetchGLState();
+ baseRenderer.ApplyStateMask(glState);
if (m_hasCamera)
- m_editorRenderer.RenderScene(m_cameraPosition);
+ {
+ if (m_camera.HasFrustumLightCulling())
+ {
+ m_editorRenderer.UpdateLightsInFrustum(currentScene, m_camera.GetFrustum());
+ }
+ else
+ {
+ m_editorRenderer.UpdateLights(currentScene);
+ }
- EDITOR_CONTEXT(renderer)->ApplyStateMask(glState);
+ m_editorRenderer.RenderScene(m_cameraPosition, m_camera);
+ }
+
+ baseRenderer.ApplyStateMask(glState);
+
+ m_fbo.Unbind();
+}
+
+bool OvEditor::Panels::GameView::HasCamera() const
+{
+ return m_hasCamera;
+}
+
+std::optional OvEditor::Panels::GameView::GetActiveFrustum() const
+{
+ return m_hasCamera ? m_camera.GetFrustum() : std::optional{};
}
diff --git a/Sources/Overload/OvEditor/src/OvEditor/Panels/HelpWindow.cpp b/Sources/Overload/OvEditor/src/OvEditor/Panels/HelpWindow.cpp
index 33fcef3a..8d81195a 100644
--- a/Sources/Overload/OvEditor/src/OvEditor/Panels/HelpWindow.cpp
+++ b/Sources/Overload/OvEditor/src/OvEditor/Panels/HelpWindow.cpp
@@ -11,25 +11,6 @@
#include
#include
-class TestWidget : public OvUI::Widgets::AWidget
-{
-public:
- TestWidget(std::string pid) { id = pid; }
-
- virtual void _Draw_Impl() override
- {
- ImGui::Columns(2, id.c_str(), false);
- ImGui::SetColumnWidth(0, 75);
- ImGui::Text("Coucou je suis a gauche");
- ImGui::NextColumn();
- ImGui::Text("Coucou je suis a droite");
-
- ImGui::Columns(1);
- }
-
- std::string id;
-};
-
OvEditor::Panels::HelpWindow::HelpWindow
(
const std::string& p_title,
diff --git a/Sources/Overload/OvEditor/src/OvEditor/Panels/Hierarchy.cpp b/Sources/Overload/OvEditor/src/OvEditor/Panels/Hierarchy.cpp
index 44ac7a9a..3a501b05 100644
--- a/Sources/Overload/OvEditor/src/OvEditor/Panels/Hierarchy.cpp
+++ b/Sources/Overload/OvEditor/src/OvEditor/Panels/Hierarchy.cpp
@@ -223,11 +223,26 @@ void OvEditor::Panels::Hierarchy::SelectActorByInstance(OvCore::ECS::Actor& p_ac
SelectActorByWidget(*result->second);
}
+void ExpandTreeNode(OvUI::Widgets::Layout::TreeNode& p_toExpand, const OvUI::Widgets::Layout::TreeNode* p_root)
+{
+ p_toExpand.Open();
+
+ if (&p_toExpand != p_root && p_toExpand.HasParent())
+ {
+ ExpandTreeNode(*static_cast(p_toExpand.GetParent()), p_root);
+ }
+}
+
void OvEditor::Panels::Hierarchy::SelectActorByWidget(OvUI::Widgets::Layout::TreeNode & p_widget)
{
UnselectActorsWidgets();
p_widget.selected = true;
+
+ if (p_widget.HasParent())
+ {
+ ExpandTreeNode(*static_cast(p_widget.GetParent()), m_sceneRoot);
+ }
}
void OvEditor::Panels::Hierarchy::AttachActorToParent(OvCore::ECS::Actor & p_actor)
diff --git a/Sources/Overload/OvEditor/src/OvEditor/Panels/MenuBar.cpp b/Sources/Overload/OvEditor/src/OvEditor/Panels/MenuBar.cpp
index 2b8d530f..9449b045 100644
--- a/Sources/Overload/OvEditor/src/OvEditor/Panels/MenuBar.cpp
+++ b/Sources/Overload/OvEditor/src/OvEditor/Panels/MenuBar.cpp
@@ -26,6 +26,7 @@
#include "OvEditor/Panels/SceneView.h"
#include "OvEditor/Panels/AssetView.h"
#include "OvEditor/Core/EditorActions.h"
+#include "OvEditor/Settings/EditorSettings.h"
using namespace OvUI::Panels;
using namespace OvUI::Widgets;
@@ -150,7 +151,6 @@ void OvEditor::Panels::MenuBar::CreateSettingsMenu()
cameraPositionMenu.CreateWidget