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>
16using namespace Ra::Core::Utils;
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 );
46 mesh->loadGeometry(
std::move( cylinder ) );
49 "Scale Gizmo Arrow", m_comp, Engine::Rendering::RenderObjectType::UI );
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 );
69 normals.getMap().fill( 0_ra );
76 "Gizmo Plane", m_comp, Engine::Rendering::RenderObjectType::UI );
78 planeDrawable->setRenderTechnique( rt );
79 planeDrawable->setMesh( mesh );
80 addRenderObject( planeDrawable );
83 updateTransform( mode, m_worldTo, m_transform );
86void 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 );
108void 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() ) {
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 ) );
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...
NormalAttribHandle::Container & normalsWithLock()
void normalsUnlock()
Release lock on vertices normals.
bool append(const MultiIndexedGeometry &other)
Mesh, own a Core::Geometry::TriangleMesh.
A component is an element that can be updated by a system. It is also linked to some other components...
hepler function to manage enum as underlying types in VariableSet