20 Gizmo( c, worldTo, t, mode ), m_initialPix( Core::Vector2::Zero() ), m_selectedAxis( -1 ) {
48void RotateGizmo::updateTransform( Gizmo::Mode mode,
49 const Core::Transform& worldTo,
50 const Core::Transform& t ) {
54 Core::Transform displayTransform = Core::Transform::Identity();
55 displayTransform.translate( m_transform.translation() );
56 if ( m_mode == LOCAL ) {
57 Core::Matrix3 R = m_transform.rotation();
58 R.col( 0 ).normalize();
59 R.col( 1 ).normalize();
60 R.col( 2 ).normalize();
61 displayTransform.rotate( R );
64 for (
auto ro : ros() ) {
65 ro->setLocalTransform( m_worldTo * displayTransform );
69void RotateGizmo::selectConstraint(
int drawableIdx ) {
71 if ( m_selectedAxis != -1 ) {
72 getControler( m_selectedAxis )->clearState();
76 if ( drawableIdx < 0 ) {
return; }
79 auto found =
std::find_if( ros().cbegin(), ros().cend(), [drawableIdx](
const auto& ro ) {
80 return ro->getIndex() == Core::Utils::Index( drawableIdx );
82 if ( found != ros().cend() ) {
83 m_selectedAxis = int(
std::distance( ros().cbegin(), found ) );
84 getControler( m_selectedAxis )->setState();
89 const Core::Vector2& nextXY,
92 static const Scalar step = Ra::Core::Math::Pi / 10_ra;
94 if ( m_selectedAxis == -1 )
return m_transform;
97 Core::Matrix3 rotationMat;
98 Core::Matrix3 scaleMat;
99 m_transform.computeRotationScaling( &rotationMat, &scaleMat );
102 const Core::Vector3 origin = m_transform.translation();
103 Core::Vector3 rotationAxis = Core::Vector3::Unit( m_selectedAxis );
104 if ( m_mode == LOCAL ) { rotationAxis = rotationMat * rotationAxis; }
105 rotationAxis.normalize();
106 const Core::Vector3 originW = m_worldTo * origin;
107 const Core::Vector3 rotationAxisW = m_worldTo * rotationAxis;
113 m_initialRot = rotationMat;
118 Core::Vector3 originalHit, currentHit;
119 bool hit1 = findPointOnPlane( cam, originW, rotationAxisW, m_initialPix, originalHit, hits1 );
120 bool hit2 = findPointOnPlane( cam, originW, rotationAxisW, nextXY, currentHit, hits2 );
125 if ( hit1 && hit2 && hits1[0] > .2_ra && hits2[0] > .2_ra ) {
127 originalHit -= originW;
128 currentHit -= originW;
132 auto c = originalHit.cross( currentHit );
133 Scalar d = originalHit.dot( currentHit );
135 angle = Core::Math::sign( c.dot( rotationAxisW ) ) *
std::atan2( c.norm(), d );
139 Core::Vector2 dir = ( cam.
projectToScreen( originW + rotationAxisW ).head<2>() -
142 if ( std::abs( dir( 0 ) ) < 1e-3_ra ) { dir << 1, 0; }
143 else if ( std::abs( dir( 1 ) ) < 1e-3_ra ) { dir << 0, 1; }
144 else { dir = Core::Vector2( dir( 1 ), -dir( 0 ) ); }
146 angle = dir.dot( ( nextXY - m_initialPix ) ) * 8_ra / diag;
150 Core::Vector2 nextXY_ = nextXY;
152 angle = int( angle / step ) * step;
153 if ( Core::Math::areApproxEqual( angle, 0_ra ) ) { nextXY_ = m_initialPix; }
155 Scalar diff = m_totalAngle - int( m_totalAngle / step ) * step;
160 m_totalAngle += angle;
161 if ( !Core::Math::areApproxEqual( angle, 0_ra ) ) {
162 auto newRot = Core::AngleAxis( angle, rotationAxis ) * rotationMat;
163 m_transform.fromPositionOrientationScale( origin, newRot, scaleMat.diagonal() );
165 m_initialPix = nextXY_;