66
77#include " OvEditor/Core/GuizmoOperations.h"
88
9- void OvEditor::Core::GuizmoOperations::StartPicking (OvCore::ECS::Actor& p_target, const OvMaths::FVector3& p_direction, const OvMaths::FVector3& p_cameraPosition )
9+ void OvEditor::Core::GuizmoOperations::StartPicking (OvCore::ECS::Actor& p_target, const OvMaths::FVector3& p_cameraPosition, EOperation p_operation, EDirection p_direction )
1010{
1111 m_target = &p_target;
12- m_direction = p_direction;
1312 m_firstMouse = true ;
13+ m_originalTransform = p_target.transform .GetFTransform ();
1414 m_distanceToActor = OvMaths::FVector3::Distance (p_cameraPosition, m_target->transform .GetWorldPosition ());
15-
15+ m_currentOperation = p_operation;
16+ m_direction = p_direction;
1617}
1718
1819void OvEditor::Core::GuizmoOperations::StopPicking ()
1920{
2021 m_target = nullptr ;
2122}
2223
23- void OvEditor::Core::GuizmoOperations::ApplyTranslation ( const OvMaths::FMatrix4& p_viewMatrix, const OvMaths::FMatrix4& p_projectionMatrix, const OvMaths::FVector2& p_viewSize ) const
24+ OvMaths::FVector3 OvEditor::Core::GuizmoOperations::GetFakeDirection ( ) const
2425{
25- float unitsPerPixel = 0 .001f ;
26+ auto result = OvMaths::FVector3 ();
27+
28+ switch (m_direction)
29+ {
30+ case OvEditor::Core::GuizmoOperations::EDirection::X:
31+ result = OvMaths::FVector3::Right;
32+ break ;
33+ case OvEditor::Core::GuizmoOperations::EDirection::Y:
34+ result = OvMaths::FVector3::Up;
35+ break ;
36+ case OvEditor::Core::GuizmoOperations::EDirection::Z:
37+ result = OvMaths::FVector3::Forward;
38+ break ;
39+ }
2640
41+ return result;
42+ }
43+
44+ OvMaths::FVector3 OvEditor::Core::GuizmoOperations::GetRealDirection (bool p_relative) const
45+ {
46+ auto result = OvMaths::FVector3 ();
47+
48+ switch (m_direction)
49+ {
50+ case OvEditor::Core::GuizmoOperations::EDirection::X:
51+ result = p_relative ? m_originalTransform.GetWorldRight () : m_originalTransform.GetLocalRight ();
52+ break ;
53+ case OvEditor::Core::GuizmoOperations::EDirection::Y:
54+ result = p_relative ? m_originalTransform.GetWorldUp () : m_originalTransform.GetLocalUp ();
55+ break ;
56+ case OvEditor::Core::GuizmoOperations::EDirection::Z:
57+ result = p_relative ? m_originalTransform.GetWorldForward () : m_originalTransform.GetLocalForward ();
58+ break ;
59+ }
60+
61+ return result;
62+ }
63+
64+ OvMaths::FVector2 OvEditor::Core::GuizmoOperations::GetScreenDirection (const OvMaths::FMatrix4& p_viewMatrix, const OvMaths::FMatrix4& p_projectionMatrix, const OvMaths::FVector2& p_viewSize) const
65+ {
2766 auto start = m_target->transform .GetWorldPosition ();
28- auto end = m_target->transform .GetWorldPosition () + m_direction;
29- auto result = OvMaths::FVector2 ();
67+ auto end = m_target->transform .GetWorldPosition () + GetRealDirection (true );
3068
69+ auto start2D = OvMaths::FVector2 ();
3170 {
32- auto clipSpacePos = p_projectionMatrix * (p_viewMatrix * OvMaths::FVector4{ end .x , end .y , end .z , 1 .0f });
71+ auto clipSpacePos = p_projectionMatrix * (p_viewMatrix * OvMaths::FVector4{ start .x , start .y , start .z , 1 .0f });
3372 auto ndcSpacePos = OvMaths::FVector3{ clipSpacePos.x , clipSpacePos.y , clipSpacePos.z } / clipSpacePos.w ;
3473 auto windowSpacePos = ((OvMaths::FVector2{ ndcSpacePos.x , ndcSpacePos.y } +1.0 ) / 2.0 );
3574 windowSpacePos.x *= p_viewSize.x ;
3675 windowSpacePos.y *= p_viewSize.y ;
37- result = windowSpacePos;
76+ start2D = windowSpacePos;
3877 }
3978
79+ auto end2D = OvMaths::FVector2 ();
4080 {
41- auto clipSpacePos = p_projectionMatrix * (p_viewMatrix * OvMaths::FVector4{ start .x , start .y , start .z , 1 .0f });
81+ auto clipSpacePos = p_projectionMatrix * (p_viewMatrix * OvMaths::FVector4{ end .x , end .y , end .z , 1 .0f });
4282 auto ndcSpacePos = OvMaths::FVector3{ clipSpacePos.x , clipSpacePos.y , clipSpacePos.z } / clipSpacePos.w ;
4383 auto windowSpacePos = ((OvMaths::FVector2{ ndcSpacePos.x , ndcSpacePos.y } +1.0 ) / 2.0 );
4484 windowSpacePos.x *= p_viewSize.x ;
4585 windowSpacePos.y *= p_viewSize.y ;
46- result - = windowSpacePos;
86+ end2D = windowSpacePos;
4787 }
4888
49- result.y *= -1 ;
50- result = OvMaths::FVector2::Normalize (result);
89+ auto result = end2D - start2D;
90+
91+ result.y *= -1 ; // Screen coordinates are reversed, so we inverse the Y
92+
93+ return OvMaths::FVector2::Normalize (result);
94+ }
95+
96+ void OvEditor::Core::GuizmoOperations::ApplyTranslation (const OvMaths::FMatrix4& p_viewMatrix, const OvMaths::FMatrix4& p_projectionMatrix, const OvMaths::FVector2& p_viewSize) const
97+ {
98+ auto unitsPerPixel = 0 .001f * m_distanceToActor;
99+ auto originPosition = m_originalTransform.GetLocalPosition ();
51100
52- auto displacement = m_currentMouse - m_previousMouse ;
101+ auto screenDirection = GetScreenDirection (p_viewMatrix, p_projectionMatrix, p_viewSize) ;
53102
54- auto translationUnit = OvMaths::FVector2::Dot (displacement, result);
55-
56- m_target->transform .TranslateLocal (m_direction * translationUnit * unitsPerPixel * m_distanceToActor);
103+ auto totalDisplacement = m_currentMouse - m_originMouse;
104+ auto translationCoefficient = OvMaths::FVector2::Dot (totalDisplacement, screenDirection);
105+
106+ m_target->transform .SetLocalPosition (originPosition + GetRealDirection () * translationCoefficient * unitsPerPixel);
107+ }
108+
109+ void OvEditor::Core::GuizmoOperations::ApplyRotation (const OvMaths::FMatrix4& p_viewMatrix, const OvMaths::FMatrix4& p_projectionMatrix, const OvMaths::FVector2& p_viewSize) const
110+ {
111+ auto unitsPerPixel = 0 .2f ;
112+ auto originRotation = m_originalTransform.GetLocalRotation ();
113+
114+ auto screenDirection = GetScreenDirection (p_viewMatrix, p_projectionMatrix, p_viewSize);
115+ screenDirection = OvMaths::FVector2 (-screenDirection.y , screenDirection.x );
116+
117+ auto totalDisplacement = m_currentMouse - m_originMouse;
118+ auto rotationCoefficient = OvMaths::FVector2::Dot (totalDisplacement, screenDirection);
119+
120+ auto rotationToApply = OvMaths::FQuaternion (OvMaths::FVector3 (GetFakeDirection () * rotationCoefficient * unitsPerPixel));
121+ m_target->transform .SetLocalRotation (originRotation * rotationToApply);
122+ }
123+
124+ void OvEditor::Core::GuizmoOperations::ApplyScale (const OvMaths::FMatrix4& p_viewMatrix, const OvMaths::FMatrix4& p_projectionMatrix, const OvMaths::FVector2& p_viewSize) const
125+ {
126+ auto unitsPerPixel = 0 .005f ;
127+ auto originScale = m_originalTransform.GetLocalScale ();
128+
129+ auto screenDirection = GetScreenDirection (p_viewMatrix, p_projectionMatrix, p_viewSize);
130+
131+ auto totalDisplacement = m_currentMouse - m_originMouse;
132+ auto scaleCoefficient = OvMaths::FVector2::Dot (totalDisplacement, screenDirection);
133+
134+ auto newScale = originScale + GetFakeDirection () * scaleCoefficient * unitsPerPixel;
135+
136+ /* Prevent scale from being negative*/
137+ newScale.x = std::max (newScale.x , 0 .0001f );
138+ newScale.y = std::max (newScale.y , 0 .0001f );
139+ newScale.z = std::max (newScale.z , 0 .0001f );
140+
141+ m_target->transform .SetLocalScale (newScale);
142+ }
143+
144+ void OvEditor::Core::GuizmoOperations::ApplyOperation (const OvMaths::FMatrix4& p_viewMatrix, const OvMaths::FMatrix4& p_projectionMatrix, const OvMaths::FVector2& p_viewSize)
145+ {
146+ switch (m_currentOperation)
147+ {
148+ case EOperation::TRANSLATION:
149+ ApplyTranslation (p_viewMatrix, p_projectionMatrix, p_viewSize);
150+ break ;
151+
152+ case EOperation::ROTATION:
153+ ApplyRotation (p_viewMatrix, p_projectionMatrix, p_viewSize);
154+ break ;
155+
156+ case EOperation::SCALE:
157+ ApplyScale (p_viewMatrix, p_projectionMatrix, p_viewSize);
158+ break ;
159+ }
57160}
58161
59162void OvEditor::Core::GuizmoOperations::SetCurrentMouse (const OvMaths::FVector2& p_mousePosition)
60163{
61164 if (m_firstMouse)
62165 {
63- m_currentMouse = m_previousMouse = p_mousePosition;
166+ m_currentMouse = m_originMouse = p_mousePosition;
64167 m_firstMouse = false ;
65168 }
66169 else
67170 {
68- m_previousMouse = m_currentMouse;
69171 m_currentMouse = p_mousePosition;
70172 }
71173}
72174
73175bool OvEditor::Core::GuizmoOperations::IsPicking () const
74176{
75177 return m_target;
76- }
178+ }
0 commit comments