Skip to content

Commit e2f59b6

Browse files
author
Adrien GIVRY
committed
Guizmo translation now working
Guizmo are rendered into the actor picking framebuffer and are a guizmo translation algorithm with mouse displacement has been implemented.
1 parent abea5db commit e2f59b6

10 files changed

Lines changed: 245 additions & 16 deletions

File tree

Sources/Overload/OvEditor/OvEditor.vcxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ xcopy "$(ProjectDir)Layout.ini" "$(SolutionDir)..\..\Build\$(ProjectName)\$(Conf
140140
<ClCompile Include="src\OvEditor\Core\EditorActions.cpp" />
141141
<ClCompile Include="src\OvEditor\Core\EditorRenderer.cpp" />
142142
<ClCompile Include="src\OvEditor\Core\EditorResources.cpp" />
143+
<ClCompile Include="src\OvEditor\Core\GuizmoOperations.cpp" />
143144
<ClCompile Include="src\OvEditor\Core\PanelsManager.cpp" />
144145
<ClCompile Include="src\OvEditor\Core\ProjectHub.cpp" />
145146
<ClCompile Include="src\OvEditor\Panels\AssetBrowser.cpp" />
@@ -169,6 +170,7 @@ xcopy "$(ProjectDir)Layout.ini" "$(SolutionDir)..\..\Build\$(ProjectName)\$(Conf
169170
<ClInclude Include="include\OvEditor\Core\EditorActions.h" />
170171
<ClInclude Include="include\OvEditor\Core\EditorRenderer.h" />
171172
<ClInclude Include="include\OvEditor\Core\EditorResources.h" />
173+
<ClInclude Include="include\OvEditor\Core\GuizmoOperations.h" />
172174
<ClInclude Include="include\OvEditor\Core\PanelsManager.h" />
173175
<ClInclude Include="include\OvEditor\Core\ProjectHub.h" />
174176
<ClInclude Include="include\OvEditor\Resources\RawShaders.h" />

Sources/Overload/OvEditor/OvEditor.vcxproj.filters

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@
9696
<ClCompile Include="src\OvEditor\Resources\RawShaders.cpp">
9797
<Filter>Source Files</Filter>
9898
</ClCompile>
99+
<ClCompile Include="src\OvEditor\Core\GuizmoOperations.cpp">
100+
<Filter>Source Files</Filter>
101+
</ClCompile>
99102
</ItemGroup>
100103
<ItemGroup>
101104
<ClInclude Include="include\OvEditor\Panels\AssetBrowser.h">
@@ -182,6 +185,9 @@
182185
<ClInclude Include="include\OvEditor\Resources\RawShaders.h">
183186
<Filter>Header Files</Filter>
184187
</ClInclude>
188+
<ClInclude Include="include\OvEditor\Core\GuizmoOperations.h">
189+
<Filter>Header Files</Filter>
190+
</ClInclude>
185191
</ItemGroup>
186192
<ItemGroup>
187193
<None Include="include\OvEditor\Core\EditorActions.inl">

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,9 @@ namespace OvEditor::Core
7575
* Render a guizmo at position
7676
* @param p_position
7777
* @param p_rotation
78+
* @param p_pickable (Determine the shader to use to render the guizmo)
7879
*/
79-
void RenderGuizmo(const OvMaths::FVector3& p_position, const OvMaths::FQuaternion& p_rotation);
80+
void RenderGuizmo(const OvMaths::FVector3& p_position, const OvMaths::FQuaternion& p_rotation, bool p_pickable = false);
8081

8182
/**
8283
* Render a model to the stencil buffer
@@ -148,6 +149,7 @@ namespace OvEditor::Core
148149
OvCore::Resources::Material m_cameraMaterial;
149150
OvCore::Resources::Material m_guizmoArrowMaterial;
150151
OvCore::Resources::Material m_guizmoBallMaterial;
152+
OvCore::Resources::Material m_guizmoPickingMaterial;
151153
OvCore::Resources::Material m_actorPickingMaterial;
152154
};
153155
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/**
2+
* @project: Overload
3+
* @author: Overload Tech.
4+
* @restrictions: This software may not be resold, redistributed or otherwise conveyed to a third party.
5+
*/
6+
7+
#pragma once
8+
9+
#include <OvEditor/Core/EditorActions.h>
10+
11+
namespace OvEditor::Core
12+
{
13+
/* Handle guizmo behaviours */
14+
class GuizmoOperations
15+
{
16+
public:
17+
/**
18+
* Starts the guizmo picking behaviour for the given target in the given direction
19+
* @param p_actor
20+
* @param p_direction
21+
* @param p_cameraPosition
22+
*/
23+
void StartPicking(OvCore::ECS::Actor& p_target, const OvMaths::FVector3& p_direction, const OvMaths::FVector3& p_cameraPosition);
24+
25+
/**
26+
* Stops the guizmo picking behaviour
27+
*/
28+
void StopPicking();
29+
30+
/**
31+
* Handle the translation behaviour
32+
* @param p_viewMatrix
33+
* @param p_projectionMatrix
34+
* @param p_viewSize
35+
*/
36+
void ApplyTranslation(const OvMaths::FMatrix4& p_viewMatrix, const OvMaths::FMatrix4& p_projectionMatrix, const OvMaths::FVector2& p_viewSize) const;
37+
38+
/**
39+
* Set the given mouse position as the current mouse position and update the previous mouse position
40+
* @param p_mousePosition
41+
*/
42+
void SetCurrentMouse(const OvMaths::FVector2& p_mousePosition);
43+
44+
/**
45+
* Returns true if the guizmo is currently picked
46+
*/
47+
bool IsPicking() const;
48+
49+
private:
50+
bool m_firstMouse = true;
51+
float m_distanceToActor = 0.0f;
52+
OvCore::ECS::Actor* m_target;
53+
OvMaths::FVector3 m_direction;
54+
OvMaths::FVector2 m_previousMouse;
55+
OvMaths::FVector2 m_currentMouse;
56+
};
57+
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#pragma once
88

99
#include "OvEditor/Panels/AViewControllable.h"
10+
#include "OvEditor/Core/GuizmoOperations.h"
1011

1112
namespace OvEditor::Panels
1213
{
@@ -50,5 +51,6 @@ namespace OvEditor::Panels
5051
private:
5152
OvCore::SceneSystem::SceneManager& m_sceneManager;
5253
OvRendering::Buffers::Framebuffer m_actorPickingFramebuffer;
54+
OvEditor::Core::GuizmoOperations m_guizmoOperations;
5355
};
5456
}

Sources/Overload/OvEditor/include/OvEditor/Resources/RawShaders.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ namespace OvEditor::Resources
2222
static std::pair<std::string, std::string> GetGrid();
2323

2424
/**
25-
* Retursn the guizmo shader
25+
* Returns the guizmo shader
2626
*/
2727
static std::pair<std::string, std::string> GetGuizmo();
2828
};

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

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,18 @@ void OvEditor::Core::EditorRenderer::InitMaterials()
102102
m_guizmoArrowMaterial.SetShader(m_context.editorResources->GetShader("Guizmo"));
103103
m_guizmoArrowMaterial.SetGPUInstances(3);
104104
m_guizmoArrowMaterial.Set("u_IsBall", false);
105+
m_guizmoArrowMaterial.Set("u_IsPickable", false);
105106

106107
/* Guizmo Ball Material */
107108
m_guizmoBallMaterial.SetShader(m_context.editorResources->GetShader("Guizmo"));
108-
m_guizmoBallMaterial.SetShader(m_context.editorResources->GetShader("Guizmo"));
109109
m_guizmoBallMaterial.Set("u_IsBall", true);
110+
m_guizmoBallMaterial.Set("u_IsPickable", false);
111+
112+
/* Guizmo Pickable Material */
113+
m_guizmoPickingMaterial.SetShader(m_context.editorResources->GetShader("Guizmo"));
114+
m_guizmoPickingMaterial.SetGPUInstances(3);
115+
m_guizmoPickingMaterial.Set("u_IsBall", false);
116+
m_guizmoPickingMaterial.Set("u_IsPickable", true);
110117

111118
/* Picking Material */
112119
m_actorPickingMaterial.SetShader(m_context.shaderManager[":Shaders\\Unlit.glsl"]);
@@ -227,14 +234,19 @@ void OvEditor::Core::EditorRenderer::RenderCameras()
227234
}
228235
}
229236

230-
void OvEditor::Core::EditorRenderer::RenderGuizmo(const OvMaths::FVector3& p_position, const OvMaths::FQuaternion& p_rotation)
237+
void OvEditor::Core::EditorRenderer::RenderGuizmo(const OvMaths::FVector3& p_position, const OvMaths::FQuaternion& p_rotation, bool p_pickable)
231238
{
232239
using namespace OvMaths;
233240

234241
FMatrix4 model = FMatrix4::Translation(p_position) * FQuaternion::ToMatrix4(FQuaternion::Normalize(p_rotation));
235-
FMatrix4 sphereModel = model * OvMaths::FMatrix4::Scaling({ 0.1f, 0.1f, 0.1f });
236-
m_context.renderer->DrawModelWithSingleMaterial(*m_context.editorResources->GetModel("Sphere"), m_guizmoBallMaterial, &sphereModel);
237-
m_context.renderer->DrawModelWithSingleMaterial(*m_context.editorResources->GetModel("Arrow"), m_guizmoArrowMaterial, &model);
242+
243+
if (!p_pickable)
244+
{
245+
FMatrix4 sphereModel = model * OvMaths::FMatrix4::Scaling({ 0.1f, 0.1f, 0.1f });
246+
m_context.renderer->DrawModelWithSingleMaterial(*m_context.editorResources->GetModel("Sphere"), m_guizmoBallMaterial, &sphereModel);
247+
}
248+
249+
m_context.renderer->DrawModelWithSingleMaterial(*m_context.editorResources->GetModel("Arrow"), p_pickable ? m_guizmoPickingMaterial : m_guizmoArrowMaterial, &model);
238250
}
239251

240252
void OvEditor::Core::EditorRenderer::RenderModelToStencil(const OvMaths::FMatrix4& p_worldMatrix, OvRendering::Resources::Model& p_model)
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/**
2+
* @project: Overload
3+
* @author: Overload Tech.
4+
* @restrictions: This software may not be resold, redistributed or otherwise conveyed to a third party.
5+
*/
6+
7+
#include "OvEditor/Core/GuizmoOperations.h"
8+
9+
void OvEditor::Core::GuizmoOperations::StartPicking(OvCore::ECS::Actor& p_target, const OvMaths::FVector3& p_direction, const OvMaths::FVector3& p_cameraPosition)
10+
{
11+
m_target = &p_target;
12+
m_direction = p_direction;
13+
m_firstMouse = true;
14+
m_distanceToActor = OvMaths::FVector3::Distance(p_cameraPosition, m_target->transform.GetWorldPosition());
15+
16+
}
17+
18+
void OvEditor::Core::GuizmoOperations::StopPicking()
19+
{
20+
m_target = nullptr;
21+
}
22+
23+
void OvEditor::Core::GuizmoOperations::ApplyTranslation(const OvMaths::FMatrix4& p_viewMatrix, const OvMaths::FMatrix4& p_projectionMatrix, const OvMaths::FVector2& p_viewSize) const
24+
{
25+
float unitsPerPixel = 0.001f;
26+
27+
auto start = m_target->transform.GetWorldPosition();
28+
auto end = m_target->transform.GetWorldPosition() + m_direction;
29+
auto result = OvMaths::FVector2();
30+
31+
{
32+
auto clipSpacePos = p_projectionMatrix * (p_viewMatrix * OvMaths::FVector4{ end.x, end.y, end.z, 1.0f });
33+
auto ndcSpacePos = OvMaths::FVector3{ clipSpacePos.x, clipSpacePos.y, clipSpacePos.z } / clipSpacePos.w;
34+
auto windowSpacePos = ((OvMaths::FVector2{ ndcSpacePos.x, ndcSpacePos.y } +1.0) / 2.0);
35+
windowSpacePos.x *= p_viewSize.x;
36+
windowSpacePos.y *= p_viewSize.y;
37+
result = windowSpacePos;
38+
}
39+
40+
{
41+
auto clipSpacePos = p_projectionMatrix * (p_viewMatrix * OvMaths::FVector4{ start.x, start.y, start.z, 1.0f });
42+
auto ndcSpacePos = OvMaths::FVector3{ clipSpacePos.x, clipSpacePos.y, clipSpacePos.z } / clipSpacePos.w;
43+
auto windowSpacePos = ((OvMaths::FVector2{ ndcSpacePos.x, ndcSpacePos.y } +1.0) / 2.0);
44+
windowSpacePos.x *= p_viewSize.x;
45+
windowSpacePos.y *= p_viewSize.y;
46+
result -= windowSpacePos;
47+
}
48+
49+
result.y *= -1;
50+
result = OvMaths::FVector2::Normalize(result);
51+
52+
auto displacement = m_currentMouse - m_previousMouse;
53+
54+
auto translationUnit = OvMaths::FVector2::Dot(displacement, result);
55+
56+
m_target->transform.TranslateLocal(m_direction * translationUnit * unitsPerPixel * m_distanceToActor);
57+
}
58+
59+
void OvEditor::Core::GuizmoOperations::SetCurrentMouse(const OvMaths::FVector2& p_mousePosition)
60+
{
61+
if (m_firstMouse)
62+
{
63+
m_currentMouse = m_previousMouse = p_mousePosition;
64+
m_firstMouse = false;
65+
}
66+
else
67+
{
68+
m_previousMouse = m_currentMouse;
69+
m_currentMouse = p_mousePosition;
70+
}
71+
}
72+
73+
bool OvEditor::Core::GuizmoOperations::IsPicking() const
74+
{
75+
return m_target;
76+
}

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

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,14 @@ void OvEditor::Panels::SceneView::RenderSceneForActorPicking()
8989
baseRenderer.SetClearColor(1.0f, 1.0f, 1.0f);
9090
baseRenderer.Clear();
9191
m_editorRenderer.RenderSceneForActorPicking();
92+
93+
if (EDITOR_EXEC(IsAnyActorSelected()))
94+
{
95+
auto& selectedActor = EDITOR_EXEC(GetSelectedActor());
96+
baseRenderer.Clear(false, true, false);
97+
m_editorRenderer.RenderGuizmo(selectedActor.transform.GetWorldPosition(), selectedActor.transform.GetWorldRotation(), true);
98+
}
99+
92100
m_actorPickingFramebuffer.Unbind();
93101
}
94102

@@ -105,6 +113,11 @@ void OvEditor::Panels::SceneView::HandleActorPicking()
105113
cursor == ImGuiMouseCursor_ResizeNESW ||
106114
cursor == ImGuiMouseCursor_ResizeAll;
107115

116+
if (EDITOR_CONTEXT(inputManager)->IsMouseButtonReleased(EMouseButton::MOUSE_BUTTON_LEFT))
117+
{
118+
m_guizmoOperations.StopPicking();
119+
}
120+
108121
bool mouseClicked = EDITOR_CONTEXT(inputManager)->IsMouseButtonPressed(EMouseButton::MOUSE_BUTTON_LEFT);
109122

110123
bool enableActorPickingDebugDraw = EDITOR_CONTEXT(inputManager)->GetKeyState(EKey::KEY_G) == EKeyState::KEY_DOWN;
@@ -129,17 +142,56 @@ void OvEditor::Panels::SceneView::HandleActorPicking()
129142
glReadPixels(static_cast<int>(mouseX), static_cast<int>(mouseY), 1, 1, GL_RGB, GL_UNSIGNED_BYTE, pixels);
130143
m_actorPickingFramebuffer.Unbind();
131144

132-
uint32_t actorID = (0 << 24) | (pixels[2] << 16) | (pixels[1] << 8) | (pixels[0] << 0);
133-
134-
if (auto actor = EDITOR_CONTEXT(sceneManager).GetCurrentScene()->FindActorByID(actorID))
145+
/* Guizmo picking */
146+
if (EDITOR_EXEC(IsAnyActorSelected()) && pixels[0] == 255 && pixels[1] == 255 && pixels[2] >= 252 && pixels[2] <= 254)
135147
{
136-
EDITOR_EXEC(SelectActor(*actor));
148+
auto& actor = EDITOR_EXEC(GetSelectedActor());
149+
150+
switch (pixels[2])
151+
{
152+
/* Guizmo X */
153+
case 253:
154+
m_guizmoOperations.StartPicking(actor, actor.transform.GetLocalRight(), m_cameraPosition);
155+
break;
156+
157+
/* Guizmo Y */
158+
case 252:
159+
m_guizmoOperations.StartPicking(actor, actor.transform.GetLocalUp(), m_cameraPosition);
160+
break;
161+
162+
/* Guizmo Z */
163+
case 254:
164+
m_guizmoOperations.StartPicking(actor, actor.transform.GetLocalForward(), m_cameraPosition);
165+
break;
166+
}
137167
}
168+
/* Actor picking */
138169
else
139170
{
140-
EDITOR_EXEC(UnselectActor());
171+
uint32_t actorID = (0 << 24) | (pixels[2] << 16) | (pixels[1] << 8) | (pixels[0] << 0);
172+
173+
if (auto actor = EDITOR_CONTEXT(sceneManager).GetCurrentScene()->FindActorByID(actorID))
174+
{
175+
EDITOR_EXEC(SelectActor(*actor));
176+
}
177+
else
178+
{
179+
EDITOR_EXEC(UnselectActor());
180+
}
141181
}
142182
}
143183

144184
m_image->textureID.d = enableActorPickingDebugDraw ? m_actorPickingFramebuffer.GetTextureID() : m_fbo.GetTextureID();
185+
186+
if (m_guizmoOperations.IsPicking())
187+
{
188+
auto mousePosition = EDITOR_CONTEXT(inputManager)->GetMousePosition();
189+
190+
auto [winWidth, winHeight] = GetSafeSize();
191+
auto projection = m_camera.GetProjectionMatrix(winWidth, winHeight);
192+
auto view = m_camera.GetViewMatrix(m_cameraPosition);
193+
194+
m_guizmoOperations.SetCurrentMouse({ static_cast<float>(mousePosition.first), static_cast<float>(mousePosition.second) });
195+
m_guizmoOperations.ApplyTranslation(view, projection, { static_cast<float>(winWidth), static_cast<float>(winHeight) });
196+
}
145197
}

0 commit comments

Comments
 (0)