Skip to content

Commit 17f4b62

Browse files
author
Adrien GIVRY
committed
Adding orthographic camera mode
Previously, our camera was only supporting perspective projection. However, it is sometimes convenient to use orthographic projection (Shadow mapping, 2D graphics, isometric games...). - A new method has been added to `OvMaths::FMatrix4` to create an orthographic projection matrix. - The rendering side camera has a new `m_projectionMode` setting and is now considering this setting for the projection calculation. An extra `m_size` setting has been added for orthographic camera. - The camera component has been updated to expose and serialize these new settings. - Lua binding has been updated to support these new methods. - Frustum drawing (Editor) has been updated to support orthographic projection. Note: Adding a new serialized member to an Overload component is currently a problem. When deserializing, we are not considering the case when the XML file doesn't contain a certain entry, and thus, some garbage values are sometimes loaded. A dirty check has been done in order to prevent the camera projection setting to be a garbage value on our old scenes (Retro-compatibility), but we should replace this by a new safer deserialization solution.
1 parent 0f4b849 commit 17f4b62

12 files changed

Lines changed: 337 additions & 73 deletions

File tree

Sources/Overload/OvCore/include/OvCore/ECS/Components/CCamera.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@ namespace OvCore::ECS::Components
4141
*/
4242
void SetFov(float p_value);
4343

44+
/**
45+
* Sets the size of the camera to the given value
46+
* @param p_value
47+
*/
48+
void SetSize(float p_value);
49+
4450
/**
4551
* Sets the near of the camera to the given value
4652
* @param p_value
@@ -71,11 +77,22 @@ namespace OvCore::ECS::Components
7177
*/
7278
void SetFrustumLightCulling(bool p_enable);
7379

80+
/**
81+
* Defines the projection mode the camera should adopt
82+
* @param p_projectionMode
83+
*/
84+
void SetProjectionMode(OvRendering::Settings::EProjectionMode p_projectionMode);
85+
7486
/**
7587
* Returns the fov of the camera
7688
*/
7789
float GetFov() const;
7890

91+
/**
92+
* Returns the size of the camera
93+
*/
94+
float GetSize() const;
95+
7996
/**
8097
* Returns the near of the camera
8198
*/
@@ -101,6 +118,11 @@ namespace OvCore::ECS::Components
101118
*/
102119
bool HasFrustumLightCulling() const;
103120

121+
/**
122+
* Returns the current projection mode
123+
*/
124+
OvRendering::Settings::EProjectionMode GetProjectionMode() const;
125+
104126
/**
105127
* Returns the OvRendering camera instance attached to this component
106128
*/

Sources/Overload/OvCore/src/OvCore/ECS/Components/CCamera.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66

77
#include <OvUI/Widgets/Drags/DragFloat.h>
8+
#include <OvUI/Widgets/Selection/ComboBox.h>
89
#include <OvUI/Plugins/DataDispatcher.h>
910

1011
#include "OvCore/ECS/Components/CCamera.h"
@@ -26,6 +27,11 @@ void OvCore::ECS::Components::CCamera::SetFov(float p_value)
2627
m_camera.SetFov(p_value);
2728
}
2829

30+
void OvCore::ECS::Components::CCamera::SetSize(float p_value)
31+
{
32+
m_camera.SetSize(p_value);
33+
}
34+
2935
void OvCore::ECS::Components::CCamera::SetNear(float p_value)
3036
{
3137
m_camera.SetNear(p_value);
@@ -46,11 +52,21 @@ void OvCore::ECS::Components::CCamera::SetFrustumLightCulling(bool p_enable)
4652
m_camera.SetFrustumLightCulling(p_enable);
4753
}
4854

55+
void OvCore::ECS::Components::CCamera::SetProjectionMode(OvRendering::Settings::EProjectionMode p_projectionMode)
56+
{
57+
m_camera.SetProjectionMode(p_projectionMode);
58+
}
59+
4960
float OvCore::ECS::Components::CCamera::GetFov() const
5061
{
5162
return m_camera.GetFov();
5263
}
5364

65+
float OvCore::ECS::Components::CCamera::GetSize() const
66+
{
67+
return m_camera.GetSize();
68+
}
69+
5470
float OvCore::ECS::Components::CCamera::GetNear() const
5571
{
5672
return m_camera.GetNear();
@@ -81,6 +97,11 @@ bool OvCore::ECS::Components::CCamera::HasFrustumLightCulling() const
8197
return m_camera.HasFrustumLightCulling();
8298
}
8399

100+
OvRendering::Settings::EProjectionMode OvCore::ECS::Components::CCamera::GetProjectionMode() const
101+
{
102+
return m_camera.GetProjectionMode();
103+
}
104+
84105
OvRendering::LowRenderer::Camera & OvCore::ECS::Components::CCamera::GetCamera()
85106
{
86107
return m_camera;
@@ -89,29 +110,63 @@ OvRendering::LowRenderer::Camera & OvCore::ECS::Components::CCamera::GetCamera()
89110
void OvCore::ECS::Components::CCamera::OnSerialize(tinyxml2::XMLDocument & p_doc, tinyxml2::XMLNode * p_node)
90111
{
91112
OvCore::Helpers::Serializer::SerializeFloat(p_doc, p_node, "fov", m_camera.GetFov());
113+
OvCore::Helpers::Serializer::SerializeFloat(p_doc, p_node, "size", m_camera.GetSize());
92114
OvCore::Helpers::Serializer::SerializeFloat(p_doc, p_node, "near", m_camera.GetNear());
93115
OvCore::Helpers::Serializer::SerializeFloat(p_doc, p_node, "far", m_camera.GetFar());
94116
OvCore::Helpers::Serializer::SerializeVec3(p_doc, p_node, "clear_color", m_camera.GetClearColor());
95117
OvCore::Helpers::Serializer::SerializeBoolean(p_doc, p_node, "frustum_geometry_culling", m_camera.HasFrustumGeometryCulling());
96118
OvCore::Helpers::Serializer::SerializeBoolean(p_doc, p_node, "frustum_light_culling", m_camera.HasFrustumLightCulling());
119+
OvCore::Helpers::Serializer::SerializeInt(p_doc, p_node, "projection_mode", static_cast<int>(m_camera.GetProjectionMode()));
97120
}
98121

99122
void OvCore::ECS::Components::CCamera::OnDeserialize(tinyxml2::XMLDocument & p_doc, tinyxml2::XMLNode * p_node)
100123
{
101124
m_camera.SetFov(OvCore::Helpers::Serializer::DeserializeFloat(p_doc, p_node, "fov"));
125+
m_camera.SetSize(OvCore::Helpers::Serializer::DeserializeFloat(p_doc, p_node, "size"));
102126
m_camera.SetNear(OvCore::Helpers::Serializer::DeserializeFloat(p_doc, p_node, "near"));
103127
m_camera.SetFar(OvCore::Helpers::Serializer::DeserializeFloat(p_doc, p_node, "far"));
104128
m_camera.SetClearColor(OvCore::Helpers::Serializer::DeserializeVec3(p_doc, p_node, "clear_color"));
105129
m_camera.SetFrustumGeometryCulling(OvCore::Helpers::Serializer::DeserializeBoolean(p_doc, p_node, "frustum_geometry_culling"));
106130
m_camera.SetFrustumLightCulling(OvCore::Helpers::Serializer::DeserializeBoolean(p_doc, p_node, "frustum_light_culling"));
131+
132+
// We have to make sure the "projection_mode" exists in the serialized component, otherwise we do not want to modify the default setting (Perspective).
133+
// This is a bad practice to have each components calling setters in `OnDeserialize` even if no XML node hasn't been found for a given property.
134+
// We should rework this system later. As it is out of the scope of the orthographic projection scope, this will be left as is for now.
135+
if (p_node->FirstChildElement("projection_mode"))
136+
{
137+
m_camera.SetProjectionMode(static_cast<OvRendering::Settings::EProjectionMode>(OvCore::Helpers::Serializer::DeserializeInt(p_doc, p_node, "projection_mode")));
138+
}
107139
}
108140

109141
void OvCore::ECS::Components::CCamera::OnInspector(OvUI::Internal::WidgetContainer& p_root)
110142
{
143+
auto currentProjectionMode = GetProjectionMode();
144+
111145
OvCore::Helpers::GUIDrawer::DrawScalar<float>(p_root, "Field of view", std::bind(&CCamera::GetFov, this), std::bind(&CCamera::SetFov, this, std::placeholders::_1));
146+
auto& fovWidget = *p_root.GetWidgets()[p_root.GetWidgets().size() - 1].first;
147+
auto& fovWidgetLabel = *p_root.GetWidgets()[p_root.GetWidgets().size() - 2].first;
148+
fovWidget.enabled = fovWidgetLabel.enabled = currentProjectionMode == OvRendering::Settings::EProjectionMode::PERSPECTIVE;
149+
150+
OvCore::Helpers::GUIDrawer::DrawScalar<float>(p_root, "Size", std::bind(&CCamera::GetSize, this), std::bind(&CCamera::SetSize, this, std::placeholders::_1));
151+
auto& sizeWidget = *p_root.GetWidgets()[p_root.GetWidgets().size() - 1].first;
152+
auto& sizeWidgetLabel = *p_root.GetWidgets()[p_root.GetWidgets().size() - 2].first;
153+
sizeWidget.enabled = sizeWidgetLabel.enabled = currentProjectionMode == OvRendering::Settings::EProjectionMode::ORTHOGRAPHIC;
154+
112155
OvCore::Helpers::GUIDrawer::DrawScalar<float>(p_root, "Near", std::bind(&CCamera::GetNear, this), std::bind(&CCamera::SetNear, this, std::placeholders::_1));
113156
OvCore::Helpers::GUIDrawer::DrawScalar<float>(p_root, "Far", std::bind(&CCamera::GetFar, this), std::bind(&CCamera::SetFar, this, std::placeholders::_1));
114157
OvCore::Helpers::GUIDrawer::DrawColor(p_root, "Clear color", [this]() {return reinterpret_cast<const OvUI::Types::Color&>(GetClearColor()); }, [this](OvUI::Types::Color p_color) { SetClearColor({ p_color.r, p_color.g, p_color.b }); }, false);
115158
OvCore::Helpers::GUIDrawer::DrawBoolean(p_root, "Frustum Geometry Culling", std::bind(&CCamera::HasFrustumGeometryCulling, this), std::bind(&CCamera::SetFrustumGeometryCulling, this, std::placeholders::_1));
116159
OvCore::Helpers::GUIDrawer::DrawBoolean(p_root, "Frustum Light Culling", std::bind(&CCamera::HasFrustumLightCulling, this), std::bind(&CCamera::SetFrustumLightCulling, this, std::placeholders::_1));
160+
161+
Helpers::GUIDrawer::CreateTitle(p_root, "Projection Mode");
162+
auto& projectionMode = p_root.CreateWidget<OvUI::Widgets::Selection::ComboBox>(static_cast<int>(GetProjectionMode()));
163+
projectionMode.choices.emplace(0, "Orthographic");
164+
projectionMode.choices.emplace(1, "Perspective");
165+
projectionMode.ValueChangedEvent += [this, &fovWidget, &fovWidgetLabel, &sizeWidget, &sizeWidgetLabel](int p_choice)
166+
{
167+
const auto newProjectionMode = static_cast<OvRendering::Settings::EProjectionMode>(p_choice);
168+
SetProjectionMode(newProjectionMode);
169+
fovWidget.enabled = fovWidgetLabel.enabled = newProjectionMode == OvRendering::Settings::EProjectionMode::PERSPECTIVE;
170+
sizeWidget.enabled = sizeWidgetLabel.enabled = newProjectionMode == OvRendering::Settings::EProjectionMode::ORTHOGRAPHIC;
171+
};
117172
}

Sources/Overload/OvCore/src/OvCore/Scripting/LuaComponentBinder.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,20 +137,30 @@ void OvCore::Scripting::LuaComponentBinder::BindComponent(sol::state & p_luaStat
137137
"SetHeight", &CPhysicalCapsule::SetHeight
138138
);
139139

140+
p_luaState.new_enum<OvRendering::Settings::EProjectionMode>("ProjectionMode",
141+
{
142+
{"ORTHOGRAPHIC", OvRendering::Settings::EProjectionMode::ORTHOGRAPHIC},
143+
{"PERSPECTIVE", OvRendering::Settings::EProjectionMode::PERSPECTIVE}
144+
});
145+
140146
p_luaState.new_usertype<CCamera>("Camera",
141147
sol::base_classes, sol::bases<AComponent>(),
142148
"GetFov", &CCamera::GetFov,
149+
"GetSize", &CCamera::GetSize,
143150
"GetNear", &CCamera::GetNear,
144151
"GetFar", &CCamera::GetFar,
145152
"GetClearColor", &CCamera::GetClearColor,
146153
"SetFov", &CCamera::SetFov,
154+
"SetSize", &CCamera::SetSize,
147155
"SetNear", &CCamera::SetNear,
148156
"SetFar", &CCamera::SetFar,
149157
"SetClearColor", &CCamera::SetClearColor,
150158
"HasFrustumGeometryCulling", &CCamera::HasFrustumGeometryCulling,
151159
"HasFrustumLightCulling", &CCamera::HasFrustumLightCulling,
160+
"GetProjectionMode", &CCamera::GetProjectionMode,
152161
"SetFrustumGeometryCulling", &CCamera::SetFrustumGeometryCulling,
153-
"SetFrustumLightCulling", &CCamera::SetFrustumLightCulling
162+
"SetFrustumLightCulling", &CCamera::SetFrustumLightCulling,
163+
"SetProjectionMode", &CCamera::SetProjectionMode
154164
);
155165

156166
p_luaState.new_usertype<CLight>("Light",

Sources/Overload/OvEditor/include/OvEditor/Core/EditorRenderer.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,20 @@ namespace OvEditor::Core
110110
*/
111111
void RenderActorOutlinePass(OvCore::ECS::Actor& p_actor, bool p_toStencil, bool p_isSelected = false);
112112

113+
/**
114+
* Render the camera perspective frustum
115+
* @param p_size
116+
* @param p_camera
117+
*/
118+
void RenderCameraPerspectiveFrustum(std::pair<uint16_t, uint16_t>& p_size, OvCore::ECS::Components::CCamera& p_camera);
119+
120+
/**
121+
* Render the camera orthographic frustum
122+
* @param p_size
123+
* @param p_camera
124+
*/
125+
void RenderCameraOrthographicFrustum(std::pair<uint16_t, uint16_t>& p_size, OvCore::ECS::Components::CCamera& p_camera);
126+
113127
/**
114128
* Render the camera frustum
115129
*/

0 commit comments

Comments
 (0)