Skip to content

Commit 5b83b13

Browse files
author
Adrien GIVRY
committed
Scene actor picking implemented
The current system only consider models and camera (Only pickable elements). As it is render based, we can't pick colliders and lights for now. We can add billboard later. The current system is limited to 255 * 255 * 255 - 1 actors (16,581,374 actors) due to the fact that our framebuffer elements are 24 bits (3 * color components).
1 parent e7eab70 commit 5b83b13

9 files changed

Lines changed: 203 additions & 61 deletions

File tree

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,29 @@ namespace OvEditor::Core
3838
*/
3939
void InitMaterials();
4040

41+
/**
42+
* Prepare the picking material by send it the color corresponding to the given actor
43+
* @param p_actor
44+
*/
45+
void PreparePickingMaterial(OvCore::ECS::Actor& p_actor);
46+
47+
/**
48+
* Calculate the model matrix for a camera attached to the given actor
49+
* @param p_actor
50+
*/
51+
OvMaths::FMatrix4 CalculateCameraModelMatrix(OvCore::ECS::Actor& p_actor);
52+
4153
/**
4254
* Render the scene
4355
* @param p_cameraPosition
4456
*/
4557
void RenderScene(const OvMaths::FVector3& p_cameraPosition);
4658

59+
/**
60+
* Render the scene for actor picking (Unlit version of the scene with colors indicating actor IDs)
61+
*/
62+
void RenderSceneForActorPicking();
63+
4764
/**
4865
* Render the User Interface
4966
*/
@@ -131,5 +148,6 @@ namespace OvEditor::Core
131148
OvCore::Resources::Material m_cameraMaterial;
132149
OvCore::Resources::Material m_guizmoArrowMaterial;
133150
OvCore::Resources::Material m_guizmoBallMaterial;
151+
OvCore::Resources::Material m_actorPickingMaterial;
134152
};
135153
}

Sources/Overload/OvEditor/include/OvEditor/Panels/AView.h

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,6 @@ namespace OvEditor::Panels
4242
*/
4343
virtual void Update(float p_deltaTime);
4444

45-
/**
46-
* Bind the FBO attached to the view
47-
*/
48-
void Bind();
49-
50-
/**
51-
* Unbind the FBO attached to the view
52-
*/
53-
void Unbind();
54-
5545
/**
5646
* Custom implementation of the draw method
5747
*/
@@ -112,7 +102,6 @@ namespace OvEditor::Panels
112102

113103
OvMaths::FVector3 m_gridColor = OvMaths::FVector3::One;
114104

115-
private:
116105
OvRendering::Buffers::Framebuffer m_fbo;
117106
};
118107
}

Sources/Overload/OvEditor/include/OvEditor/Panels/SceneView.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,23 @@ namespace OvEditor::Panels
2727
);
2828

2929
/**
30-
* Update the scene view (Inputs logic)
31-
* @param p_deltaTime
30+
* Custom implementation of the render method
3231
*/
33-
virtual void Update(float p_deltaTime) override;
32+
virtual void _Render_Impl() override;
3433

3534
/**
36-
* Custom implementation of the render method
35+
* Render the actual scene
36+
* @param p_defaultRenderState
3737
*/
38-
virtual void _Render_Impl() override;
38+
void RenderScene(uint8_t p_defaultRenderState);
39+
40+
/**
41+
* Render the scene for actor picking and handle the logic behind it
42+
*/
43+
void HandleActorPicking();
3944

4045
private:
4146
OvCore::SceneSystem::SceneManager& m_sceneManager;
47+
OvRendering::Buffers::Framebuffer m_actorPickingFramebuffer;
4248
};
4349
}

Sources/Overload/OvEditor/src/OvEditor/Core/Editor.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,8 @@ void OvEditor::Core::Editor::PreUpdate()
8282
void OvEditor::Core::Editor::Update(float p_deltaTime)
8383
{
8484
UpdateCurrentEditorMode(p_deltaTime);
85-
UpdateEditorPanels(p_deltaTime);
8685
PrepareRendering(p_deltaTime);
86+
UpdateEditorPanels(p_deltaTime);
8787
RenderViews(p_deltaTime);
8888
RenderEditorUI(p_deltaTime);
8989
m_editorActions.ExecuteDelayedActions();

Sources/Overload/OvEditor/src/OvEditor/Core/EditorRenderer.cpp

Lines changed: 98 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#include <OvCore/ECS/Components/CDirectionalLight.h>
1414
#include <OvCore/ECS/Components/CSpotLight.h>
1515

16+
#include <OvDebug/Utils/Assertion.h>
17+
1618
#include "OvEditor/Core/EditorRenderer.h"
1719
#include "OvEditor/Core/EditorResources.h"
1820
#include "OvEditor/Panels/AView.h"
@@ -105,6 +107,32 @@ void OvEditor::Core::EditorRenderer::InitMaterials()
105107
m_guizmoBallMaterial.SetShader(m_context.editorResources->GetShader("Guizmo"));
106108
m_guizmoBallMaterial.SetShader(m_context.editorResources->GetShader("Guizmo"));
107109
m_guizmoBallMaterial.Set("u_IsBall", true);
110+
111+
/* Picking Material */
112+
m_actorPickingMaterial.SetShader(m_context.shaderManager[":Shaders\\Unlit.glsl"]);
113+
m_actorPickingMaterial.Set("u_Diffuse", FVector4(1.f, 1.f, 1.f, 1.0f));
114+
m_actorPickingMaterial.Set<OvRendering::Resources::Texture*>("u_DiffuseMap", nullptr);
115+
m_actorPickingMaterial.SetFrontfaceCulling(false);
116+
m_actorPickingMaterial.SetBackfaceCulling(false);
117+
}
118+
119+
void OvEditor::Core::EditorRenderer::PreparePickingMaterial(OvCore::ECS::Actor& p_actor)
120+
{
121+
uint32_t actorID = static_cast<uint32_t>(p_actor.GetID());
122+
123+
auto bytes = reinterpret_cast<uint8_t*>(&actorID);
124+
auto color = FVector4{ bytes[0] / 255.0f, bytes[1] / 255.0f, bytes[2] / 255.0f, 1.0f };
125+
126+
m_actorPickingMaterial.Set("u_Diffuse", color);
127+
}
128+
129+
OvMaths::FMatrix4 OvEditor::Core::EditorRenderer::CalculateCameraModelMatrix(OvCore::ECS::Actor& p_actor)
130+
{
131+
auto translation = FMatrix4::Translation(p_actor.transform.GetWorldPosition());
132+
auto rotation = FQuaternion::ToMatrix4(p_actor.transform.GetWorldRotation());
133+
auto scale = FMatrix4::Scaling({ 0.4f, 0.4f, 0.4f });
134+
135+
return translation * rotation * scale;
108136
}
109137

110138
void OvEditor::Core::EditorRenderer::RenderScene(const OvMaths::FVector3& p_cameraPosition)
@@ -115,6 +143,69 @@ void OvEditor::Core::EditorRenderer::RenderScene(const OvMaths::FVector3& p_came
115143
m_context.lightSSBO->Unbind();
116144
}
117145

146+
void OvEditor::Core::EditorRenderer::RenderSceneForActorPicking()
147+
{
148+
auto& scene = *m_context.sceneManager.GetCurrentScene();
149+
150+
/* Render models */
151+
for (auto modelRenderer : scene.GetFastAccessComponents().modelRenderers)
152+
{
153+
auto& actor = modelRenderer->owner;
154+
155+
if (actor.IsActive())
156+
{
157+
if (auto model = modelRenderer->GetModel())
158+
{
159+
160+
if (auto materialRenderer = modelRenderer->owner.GetComponent<OvCore::ECS::Components::CMaterialRenderer>())
161+
{
162+
const OvCore::ECS::Components::CMaterialRenderer::MaterialList& materials = materialRenderer->GetMaterials();
163+
auto modelMatrix = actor.transform.GetWorldMatrix();
164+
PreparePickingMaterial(actor);
165+
166+
for (auto mesh : model->GetMeshes())
167+
{
168+
OvCore::Resources::Material* material = nullptr;
169+
170+
if (mesh->GetMaterialIndex() < MAX_MATERIAL_COUNT)
171+
{
172+
material = materials.at(mesh->GetMaterialIndex());
173+
if (!material || !material->GetShader())
174+
material = &m_emptyMaterial;
175+
}
176+
177+
if (material)
178+
{
179+
m_actorPickingMaterial.SetBackfaceCulling(material->HasBackfaceCulling());
180+
m_actorPickingMaterial.SetFrontfaceCulling(material->HasFrontfaceCulling());
181+
m_actorPickingMaterial.SetColorWriting(material->HasColorWriting());
182+
m_actorPickingMaterial.SetDepthTest(material->HasDepthTest());
183+
m_actorPickingMaterial.SetDepthWriting(material->HasDepthWriting());
184+
185+
m_context.renderer->DrawMesh(*mesh, m_actorPickingMaterial, &modelMatrix);
186+
}
187+
}
188+
}
189+
}
190+
}
191+
}
192+
193+
/* Render cameras */
194+
for (auto camera : m_context.sceneManager.GetCurrentScene()->GetFastAccessComponents().cameras)
195+
{
196+
auto& actor = camera->owner;
197+
198+
if (actor.IsActive())
199+
{
200+
PreparePickingMaterial(actor);
201+
auto& model = *m_context.editorResources->GetModel("Camera");
202+
auto modelMatrix = CalculateCameraModelMatrix(actor);
203+
204+
m_context.renderer->DrawModelWithSingleMaterial(model, m_actorPickingMaterial, &modelMatrix);
205+
}
206+
}
207+
}
208+
118209
void OvEditor::Core::EditorRenderer::RenderUI()
119210
{
120211
m_context.uiManager->Render();
@@ -124,10 +215,14 @@ void OvEditor::Core::EditorRenderer::RenderCameras()
124215
{
125216
for (auto camera : m_context.sceneManager.GetCurrentScene()->GetFastAccessComponents().cameras)
126217
{
127-
if (camera->owner.IsActive())
218+
auto& actor = camera->owner;
219+
220+
if (actor.IsActive())
128221
{
129-
auto modelMatrix = FMatrix4::Translation(camera->owner.transform.GetWorldPosition()) * FQuaternion::ToMatrix4(camera->owner.transform.GetWorldRotation()) * FMatrix4::Scaling({ 0.4f, 0.4f, 0.4f });
130-
m_context.renderer->DrawModelWithSingleMaterial(*m_context.editorResources->GetModel("Camera"), m_cameraMaterial, &modelMatrix);
222+
auto& model = *m_context.editorResources->GetModel("Camera");
223+
auto modelMatrix = CalculateCameraModelMatrix(actor);
224+
225+
m_context.renderer->DrawModelWithSingleMaterial(model, m_cameraMaterial, &modelMatrix);
131226
}
132227
}
133228
}

Sources/Overload/OvEditor/src/OvEditor/Panels/AView.cpp

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -25,29 +25,11 @@ OvEditor::Panels::AView::AView
2525

2626
void OvEditor::Panels::AView::Update(float p_deltaTime)
2727
{
28-
Bind();
29-
3028
auto[winWidth, winHeight] = GetSafeSize();
3129

3230
m_image->size = OvMaths::FVector2(static_cast<float>(winWidth), static_cast<float>(winHeight));
3331

3432
m_fbo.Resize(winWidth, winHeight);
35-
36-
Unbind();
37-
}
38-
39-
void OvEditor::Panels::AView::Bind()
40-
{
41-
auto[winWidth, winHeight] = GetSafeSize();
42-
43-
glViewport(0, 0, winWidth, winHeight);
44-
45-
m_fbo.Bind();
46-
}
47-
48-
void OvEditor::Panels::AView::Unbind()
49-
{
50-
m_fbo.Unbind();
5133
}
5234

5335
void OvEditor::Panels::AView::_Draw_Impl()
@@ -67,10 +49,9 @@ void OvEditor::Panels::AView::Render()
6749
auto projection = m_camera.GetProjectionMatrix(winWidth, winHeight);
6850
auto view = m_camera.GetViewMatrix(m_cameraPosition);
6951
EDITOR_CONTEXT(shapeDrawer)->SetViewProjection(projection * view);
52+
glViewport(0, 0, winWidth, winHeight); // TODO: Move this OpenGL call to OvRendering
7053

71-
Bind();
7254
_Render_Impl();
73-
Unbind();
7455
}
7556

7657
void OvEditor::Panels::AView::SetCameraPosition(const OvMaths::FVector3 & p_position)

Sources/Overload/OvEditor/src/OvEditor/Panels/AssetView.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ void OvEditor::Panels::AssetView::_Render_Impl()
4949
{
5050
auto& baseRenderer = *EDITOR_CONTEXT(renderer).get();
5151

52+
m_fbo.Bind();
53+
5254
baseRenderer.SetStencilMask(0xFF);
5355
baseRenderer.Clear(m_camera);
5456
baseRenderer.SetStencilMask(0x00);
@@ -68,6 +70,8 @@ void OvEditor::Panels::AssetView::_Render_Impl()
6870
m_editorRenderer.RenderMaterialAsset(**pval);
6971

7072
baseRenderer.ApplyStateMask(glState);
73+
74+
m_fbo.Unbind();
7175
}
7276

7377
void OvEditor::Panels::AssetView::SetResource(ViewableResource p_resource)

Sources/Overload/OvEditor/src/OvEditor/Panels/GameView.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ void OvEditor::Panels::GameView::Update(float p_deltaTime)
4545
void OvEditor::Panels::GameView::_Render_Impl()
4646
{
4747
auto& baseRenderer = *EDITOR_CONTEXT(renderer).get();
48+
49+
m_fbo.Bind();
4850

4951
baseRenderer.Clear(m_camera);
5052

@@ -54,5 +56,8 @@ void OvEditor::Panels::GameView::_Render_Impl()
5456
if (m_hasCamera)
5557
m_editorRenderer.RenderScene(m_cameraPosition);
5658

59+
5760
baseRenderer.ApplyStateMask(glState);
61+
62+
m_fbo.Unbind();
5863
}

0 commit comments

Comments
 (0)