1 #include <Gui/Viewer/Gizmo/ScaleGizmo.hpp>
3 #include <Core/Containers/VectorArray.hpp>
4 #include <Core/Geometry/MeshPrimitives.hpp>
5 #include <Core/Utils/Color.hpp>
7 #include <Core/Asset/Camera.hpp>
8 #include <Engine/Data/Mesh.hpp>
9 #include <Engine/Rendering/RenderObject.hpp>
10 #include <Engine/Rendering/RenderTechnique.hpp>
11 #include <Engine/Scene/CameraComponent.hpp>
16 using namespace Ra::Core::Utils;
18 ScaleGizmo::ScaleGizmo( Engine::Scene::Component* c,
19 const Core::Transform& worldTo,
20 const Core::Transform& t,
22 Gizmo( c, worldTo, t, mode ),
23 m_prevScale( Core::Vector3::Ones() ),
24 m_startPoint( Core::Vector3::Zero() ),
25 m_initialPix( Core::Vector2::Zero() ),
27 m_selectedPlane( -1 ) {
28 constexpr Scalar arrowScale = .1_ra;
29 constexpr Scalar axisWidth = .05_ra;
30 constexpr Scalar arrowFrac = .125_ra;
31 constexpr Scalar radius = arrowScale * axisWidth / 2_ra;
33 for ( uint i = 0; i < 3; ++i ) {
34 Core::Vector3 cylinderEnd = Core::Vector3::Zero();
35 cylinderEnd[i] = ( 1_ra - arrowFrac );
36 Core::Geometry::TriangleMesh cylinder = Core::Geometry::makeCylinder(
37 Core::Vector3::Zero(), arrowScale * cylinderEnd, radius, 32 );
39 boxBounds.extend( Core::Vector3( -radius * 2_ra, -radius * 2_ra, -radius * 2_ra ) );
40 boxBounds.extend( Core::Vector3( radius * 2_ra, radius * 2_ra, radius * 2_ra ) );
41 boxBounds.translate( arrowScale * cylinderEnd );
42 Core::Geometry::TriangleMesh box = Core::Geometry::makeSharpBox( boxBounds );
43 cylinder.append( box );
45 std::shared_ptr<Engine::Data::Mesh> mesh(
new Engine::Data::Mesh(
"Scale Gizmo Arrow" ) );
46 mesh->loadGeometry( std::move( cylinder ) );
48 Engine::Rendering::RenderObject* arrowDrawable =
new Engine::Rendering::RenderObject(
49 "Scale Gizmo Arrow", m_comp, Engine::Rendering::RenderObjectType::UI );
50 auto rt = std::shared_ptr<Engine::Rendering::RenderTechnique>( makeRenderTechnique( i ) );
51 arrowDrawable->setRenderTechnique( rt );
52 arrowDrawable->setMesh( mesh );
53 addRenderObject( arrowDrawable );
56 for ( uint i = 0; i < 3; ++i ) {
57 Core::Vector3 axis = Core::Vector3::Zero();
58 axis[( i == 0 ? 1 : ( i == 1 ? 0 : 2 ) )] = 1;
59 Core::Transform T = Core::Transform::Identity();
60 T.rotate( Core::AngleAxis( Core::Math::PiDiv2, axis ) );
61 T.translation()[( i + 1 ) % 3] += arrowFrac * arrowScale * 3;
62 T.translation()[( i + 2 ) % 3] += arrowFrac * arrowScale * 3;
64 Core::Geometry::TriangleMesh plane = Core::Geometry::makePlaneGrid(
65 1, 1, Core::Vector2( arrowFrac * arrowScale, arrowFrac * arrowScale ), T );
68 auto& normals = plane.normalsWithLock();
69 normals.getMap().fill( 0_ra );
70 plane.normalsUnlock();
72 std::shared_ptr<Engine::Data::Mesh> mesh(
new Engine::Data::Mesh(
"Gizmo Plane" ) );
73 mesh->loadGeometry( std::move( plane ) );
75 Engine::Rendering::RenderObject* planeDrawable =
new Engine::Rendering::RenderObject(
76 "Gizmo Plane", m_comp, Engine::Rendering::RenderObjectType::UI );
77 auto rt = std::shared_ptr<Engine::Rendering::RenderTechnique>( makeRenderTechnique( i ) );
78 planeDrawable->setRenderTechnique( rt );
79 planeDrawable->setMesh( mesh );
80 addRenderObject( planeDrawable );
83 updateTransform( mode, m_worldTo, m_transform );
86 void ScaleGizmo::updateTransform( Gizmo::Mode mode,
87 const Core::Transform& worldTo,
88 const Core::Transform& t ) {
92 Core::Transform displayTransform = Core::Transform::Identity();
93 displayTransform.translate( m_transform.translation() );
96 Core::Matrix3 R = m_transform.rotation();
97 R.col( 0 ).normalize();
98 R.col( 1 ).normalize();
99 R.col( 2 ).normalize();
100 displayTransform.rotate( R );
103 for (
const auto& ro : ros() ) {
104 ro->setLocalTransform( m_worldTo * displayTransform );
108 void ScaleGizmo::selectConstraint(
int drawableIdx ) {
110 for ( uint i = 0; i < 6; ++i ) {
111 getControler( i )->clearState();
115 m_selectedPlane = -1;
117 if ( drawableIdx < 0 ) {
return; }
120 auto found = std::find_if( ros().cbegin(), ros().cend(), [drawableIdx](
const auto& ro ) {
121 return ro->getIndex() == Core::Utils::Index( drawableIdx );
123 if ( found != ros().cend() ) {
124 int i = int( std::distance( ros().cbegin(), found ) );
125 getControler( i )->setState();
126 ( i < 3 ) ? m_selectedAxis = i : m_selectedPlane = i - 3;
128 if ( m_selectedPlane != -1 ) {
129 getControler( ( m_selectedPlane + 1 ) % 3 )->setState();
130 getControler( ( m_selectedPlane + 2 ) % 3 )->setState();
136 const Core::Vector2& nextXY,
139 static const Scalar step = .2_ra;
145 for ( uint i = 0; i < 6; ++i ) {
146 getControler( i )->setState();
150 for ( uint i = 0; i < 6; ++i ) {
151 getControler( i )->clearState();
153 if ( m_selectedAxis > -1 ) { getControler( m_selectedAxis )->setState(); }
155 if ( m_selectedPlane > -1 ) {
156 getControler( m_selectedPlane + 3 )->setState();
158 getControler( ( m_selectedPlane + 1 ) % 3 )->setState();
159 getControler( ( m_selectedPlane + 2 ) % 3 )->setState();
164 if ( m_selectedAxis == -1 && m_selectedPlane == -1 && !whole ) {
return m_transform; }
167 int dir = whole ? 0 : std::max( m_selectedAxis, m_selectedPlane );
168 const Core::Vector3 origin = m_transform.translation();
169 Core::Vector3 scaleDir = Core::Vector3( m_transform.rotation() * Core::Vector3::Unit( dir ) );
173 std::vector<Scalar> hits;
175 Core::Vector3 endPoint;
177 found = findPointOnPlane( cam, origin, scaleDir, m_initialPix + nextXY, endPoint, hits );
179 else if ( m_selectedAxis > -1 ) {
180 found = findPointOnAxis( cam, origin, scaleDir, m_initialPix + nextXY, endPoint, hits );
182 else if ( m_selectedPlane >= 0 ) {
183 found = findPointOnPlane( cam, origin, scaleDir, m_initialPix + nextXY, endPoint, hits );
185 if ( !found ) {
return m_transform; }
190 m_startPos = m_transform.translation();
191 m_prevScale = Core::Vector3::Ones();
192 m_startPoint = endPoint;
196 const Scalar a = ( endPoint - m_startPos ).squaredNorm();
197 if ( a < 1e-3_ra ) {
return m_transform; }
200 const Core::Vector3 b = m_startPoint - m_startPos;
201 Scalar scale = std::sqrt( a ) / b.norm();
202 if ( stepped ) { scale = int( scale / step + 1 ) * step; }
205 m_transform.scale( m_prevScale );
206 if ( whole ) { m_prevScale = scale * Core::Vector3::Ones(); }
207 else if ( m_selectedAxis > -1 ) {
208 m_prevScale = Core::Vector3::Ones();
209 m_prevScale[m_selectedAxis] = scale;
211 else if ( m_selectedPlane >= 0 ) {
212 m_prevScale = Core::Vector3::Ones();
213 m_prevScale[( m_selectedPlane + 1 ) % 3] = scale;
214 m_prevScale[( m_selectedPlane + 2 ) % 3] = scale;
216 m_transform.scale( m_prevScale );
217 m_prevScale = m_prevScale.cwiseInverse();
223 const Core::Vector2& ) {
224 m_initialPix = Core::Vector2::Zero();
Camera class storing the Camera frame and the projection properties The view direction is -z in camer...