Radium Engine  1.5.0
TranslateGizmo.cpp
1 #include <Gui/Viewer/Gizmo/TranslateGizmo.hpp>
2 
3 #include <Core/Containers/VectorArray.hpp>
4 #include <Core/Geometry/MeshPrimitives.hpp>
5 #include <Core/Utils/Color.hpp>
6 
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>
12 
13 namespace Ra {
14 namespace Gui {
15 
16 TranslateGizmo::TranslateGizmo( Engine::Scene::Component* c,
17  const Core::Transform& worldTo,
18  const Core::Transform& t,
19  Mode mode ) :
20  Gizmo( c, worldTo, t, mode ),
21  m_startPoint( Core::Vector3::Zero() ),
22  m_initialPix( Core::Vector2::Zero() ),
23  m_selectedAxis( -1 ),
24  m_selectedPlane( -1 ) {
25  constexpr Scalar arrowScale = .1_ra;
26  constexpr Scalar axisWidth = .05_ra;
27  constexpr Scalar arrowFrac = .15_ra;
28 
29  for ( uint i = 0; i < 3; ++i ) {
30  Core::Vector3 cylinderEnd = Core::Vector3::Zero();
31  cylinderEnd[i] = ( 1_ra - arrowFrac );
32  Core::Vector3 arrowEnd = Core::Vector3::Zero();
33  arrowEnd[i] = 1_ra;
34  Core::Geometry::TriangleMesh cylinder = Core::Geometry::makeCylinder(
35  Core::Vector3::Zero(), arrowScale * cylinderEnd, arrowScale * axisWidth / 2_ra, 32 );
36  Core::Geometry::TriangleMesh cone = Core::Geometry::makeCone(
37  arrowScale * cylinderEnd, arrowScale * arrowEnd, arrowScale * arrowFrac / 2_ra, 32 );
38  cylinder.append( cone );
39 
40  std::shared_ptr<Engine::Data::Mesh> mesh(
41  new Engine::Data::Mesh( "Translate Gizmo Arrow" ) );
42  mesh->loadGeometry( std::move( cylinder ) );
43 
44  Engine::Rendering::RenderObject* arrowDrawable = new Engine::Rendering::RenderObject(
45  "Translate Gizmo Arrow", m_comp, Engine::Rendering::RenderObjectType::UI );
46  auto rt = std::shared_ptr<Engine::Rendering::RenderTechnique>( makeRenderTechnique( i ) );
47  arrowDrawable->setRenderTechnique( rt );
48  arrowDrawable->setMesh( mesh );
49  addRenderObject( arrowDrawable );
50  }
51 
52  for ( uint i = 0; i < 3; ++i ) {
53  Core::Vector3 axis = Core::Vector3::Zero();
54  axis[( i == 0 ? 1 : ( i == 1 ? 0 : 2 ) )] = 1;
55  Core::Transform T = Core::Transform::Identity();
56  T.rotate( Core::AngleAxis( Core::Math::PiDiv2, axis ) );
57  T.translation()[( i + 1 ) % 3] += arrowScale / 8_ra * 3_ra;
58  T.translation()[( i + 2 ) % 3] += arrowScale / 8_ra * 3_ra;
59 
60  Core::Geometry::TriangleMesh plane = Core::Geometry::makePlaneGrid(
61  1, 1, Core::Vector2( arrowScale / 8_ra, arrowScale / 8_ra ), T );
62 
63  // \FIXME this hack is here to be sure the plane will be selected (see shader)
64 
65  auto& normals = plane.normalsWithLock();
66  normals.getMap().fill( 0_ra );
67  plane.normalsUnlock();
68 
69  std::shared_ptr<Engine::Data::Mesh> mesh( new Engine::Data::Mesh( "Gizmo Plane" ) );
70  mesh->loadGeometry( std::move( plane ) );
71 
72  Engine::Rendering::RenderObject* planeDrawable = new Engine::Rendering::RenderObject(
73  "Gizmo Plane", m_comp, Engine::Rendering::RenderObjectType::UI );
74  auto rt = std::shared_ptr<Engine::Rendering::RenderTechnique>( makeRenderTechnique( i ) );
75  planeDrawable->setRenderTechnique( rt );
76  planeDrawable->setMesh( mesh );
77  addRenderObject( planeDrawable );
78  }
79 
80  updateTransform( mode, m_worldTo, m_transform );
81 }
82 
83 void TranslateGizmo::updateTransform( Gizmo::Mode mode,
84  const Core::Transform& worldTo,
85  const Core::Transform& t ) {
86  m_mode = mode;
87  m_worldTo = worldTo;
88  m_transform = t;
89  Core::Transform displayTransform = Core::Transform::Identity();
90  displayTransform.translate( m_transform.translation() );
91  if ( m_mode == LOCAL ) {
92  Core::Matrix3 R = m_transform.rotation();
93  R.col( 0 ).normalize();
94  R.col( 1 ).normalize();
95  R.col( 2 ).normalize();
96  displayTransform.rotate( R );
97  }
98 
99  for ( auto ro : ros() ) {
100  ro->setLocalTransform( m_worldTo * displayTransform );
101  }
102 }
103 
104 void TranslateGizmo::selectConstraint( int drawableIdx ) {
105  // deselect previously selected axis
106  if ( m_selectedAxis != -1 ) {
107  getControler( m_selectedAxis )->clearState();
108  m_selectedAxis = -1;
109  }
110  // deselect previously selected plane
111  if ( m_selectedPlane != -1 ) {
112  getControler( m_selectedPlane + 3 )->clearState();
113  getControler( ( m_selectedPlane + 1 ) % 3 )->clearState();
114  getControler( ( m_selectedPlane + 2 ) % 3 )->clearState();
115  m_selectedPlane = -1;
116  }
117 
118  // Return if no component is selected
119  if ( drawableIdx < 0 ) { return; }
120 
121  // update the state of the selected component
122  auto found = std::find_if( ros().cbegin(), ros().cend(), [drawableIdx]( const auto& ro ) {
123  return ro->getIndex() == Core::Utils::Index( drawableIdx );
124  } );
125  if ( found != ros().cend() ) {
126  int i = int( std::distance( ros().cbegin(), found ) );
127  getControler( i )->setState();
128  ( i < 3 ) ? m_selectedAxis = i : m_selectedPlane = i - 3;
129  // Activate the axes correponding to the selected plane
130  if ( m_selectedPlane != -1 ) {
131  getControler( ( m_selectedPlane + 1 ) % 3 )->setState();
132  getControler( ( m_selectedPlane + 2 ) % 3 )->setState();
133  }
134  }
135 }
136 
137 Core::Transform TranslateGizmo::mouseMove( const Core::Asset::Camera& cam,
138  const Core::Vector2& nextXY,
139  bool stepped,
140  bool whole ) {
141  CORE_UNUSED( whole );
142  static const Scalar step = .2_ra;
143 
144  if ( m_selectedAxis == -1 && m_selectedPlane == -1 ) return m_transform;
145 
146  // Get gizmo center and translation axis / plane normal
147  std::vector<Scalar> hits;
148  int axis = std::max( m_selectedAxis, m_selectedPlane );
149  const Core::Vector3 origin = m_transform.translation();
150  const Core::Vector3 translateDir =
151  m_mode == LOCAL ? Core::Vector3( m_transform.rotation() * Core::Vector3::Unit( axis ) )
152  : Core::Vector3::Unit( axis );
153 
154  // Project the clicked points against the axis defined by the translation axis,
155  // or the planes defined by the translation plane.
156  Ra::Core::Vector3 endPoint;
157  bool found = false;
158  if ( m_selectedAxis > -1 ) {
159  found = findPointOnAxis( cam, origin, translateDir, m_initialPix + nextXY, endPoint, hits );
160  }
161  else if ( m_selectedPlane > -1 ) {
162  found =
163  findPointOnPlane( cam, origin, translateDir, m_initialPix + nextXY, endPoint, hits );
164  }
165 
166  if ( found ) {
167  // Initialize translation
168  if ( !m_start ) {
169  m_start = true;
170  m_startPoint = endPoint;
171  m_initialTrans = origin;
172  }
173 
174  // Apply translation
175  Ra::Core::Vector3 tr = endPoint - m_startPoint;
176  if ( stepped ) { tr = int( tr.norm() / step ) * step * tr.normalized(); }
177  m_transform.translation() = m_initialTrans + tr;
178  }
179 
180  return m_transform;
181 }
182 
183 void TranslateGizmo::setInitialState( const Core::Asset::Camera& /*cam*/,
184  const Core::Vector2& /*initialXY*/ ) {
185  m_initialPix = Core::Vector2::Zero();
186  m_start = false;
187 }
188 
189 } // namespace Gui
190 } // namespace Ra
Camera class storing the Camera frame and the projection properties The view direction is -z in camer...
Definition: Camera.hpp:16
Definition: Cage.cpp:3