TRACK_BALL: Allow two input devices to simultaneously pan & rotate
Instead of the mouse pan and drag algorithms calculating the new position or rotation values relative to a starting value, the new values are calculated relative to the current values. This allows the user to use a second input device to move or rotate the view at the same time without its change being undone by the mouse.
This commit is contained in:
parent
27063688b3
commit
cd82a927c2
|
@ -125,7 +125,12 @@ void CAMERA::SetBoardLookAtPos( const SFVEC3F& aBoardPos )
|
||||||
if( m_board_lookat_pos_init != aBoardPos )
|
if( m_board_lookat_pos_init != aBoardPos )
|
||||||
{
|
{
|
||||||
m_board_lookat_pos_init = aBoardPos;
|
m_board_lookat_pos_init = aBoardPos;
|
||||||
SetLookAtPos( aBoardPos );
|
m_lookat_pos = aBoardPos;
|
||||||
|
|
||||||
|
m_parametersChanged = true;
|
||||||
|
|
||||||
|
updateViewMatrix();
|
||||||
|
updateFrustum();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -109,8 +109,7 @@ public:
|
||||||
float GetNear() const { return m_frustum.nearD; }
|
float GetNear() const { return m_frustum.nearD; }
|
||||||
float GetFar() const { return m_frustum.farD; }
|
float GetFar() const { return m_frustum.farD; }
|
||||||
|
|
||||||
void SetBoardLookAtPos( const SFVEC3F& aBoardPos );
|
void SetBoardLookAtPos( const SFVEC3F& aBoardPos );
|
||||||
virtual void SetLookAtPos( const SFVEC3F& aLookAtPos ) = 0;
|
|
||||||
|
|
||||||
void SetLookAtPos_T1( const SFVEC3F& aLookAtPos )
|
void SetLookAtPos_T1( const SFVEC3F& aLookAtPos )
|
||||||
{
|
{
|
||||||
|
|
|
@ -33,22 +33,20 @@
|
||||||
#include "../3d_math.h"
|
#include "../3d_math.h"
|
||||||
#include <wx/log.h>
|
#include <wx/log.h>
|
||||||
|
|
||||||
|
#include <glm/gtc/quaternion.hpp>
|
||||||
|
|
||||||
TRACK_BALL::TRACK_BALL( float aInitialDistance ) :
|
TRACK_BALL::TRACK_BALL( float aInitialDistance ) :
|
||||||
CAMERA( aInitialDistance )
|
CAMERA( aInitialDistance )
|
||||||
{
|
{
|
||||||
wxLogTrace( m_logTrace, wxT( "TRACK_BALL::TRACK_BALL" ) );
|
wxLogTrace( m_logTrace, wxT( "TRACK_BALL::TRACK_BALL" ) );
|
||||||
|
|
||||||
memset( m_quat, 0, sizeof( m_quat ) );
|
|
||||||
memset( m_quat_t0, 0, sizeof( m_quat_t0 ) );
|
memset( m_quat_t0, 0, sizeof( m_quat_t0 ) );
|
||||||
memset( m_quat_t1, 0, sizeof( m_quat_t1 ) );
|
memset( m_quat_t1, 0, sizeof( m_quat_t1 ) );
|
||||||
|
|
||||||
trackball( m_quat, 0.0, 0.0, 0.0, 0.0 );
|
|
||||||
trackball( m_quat_t0, 0.0, 0.0, 0.0, 0.0 );
|
trackball( m_quat_t0, 0.0, 0.0, 0.0, 0.0 );
|
||||||
trackball( m_quat_t1, 0.0, 0.0, 0.0, 0.0 );
|
trackball( m_quat_t1, 0.0, 0.0, 0.0, 0.0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TRACK_BALL::Drag( const wxPoint& aNewMousePosition )
|
void TRACK_BALL::Drag( const wxPoint& aNewMousePosition )
|
||||||
{
|
{
|
||||||
m_parametersChanged = true;
|
m_parametersChanged = true;
|
||||||
|
@ -64,34 +62,15 @@ void TRACK_BALL::Drag( const wxPoint& aNewMousePosition )
|
||||||
zoom * ( 2.0 * aNewMousePosition.x - m_windowSize.x ) / m_windowSize.x,
|
zoom * ( 2.0 * aNewMousePosition.x - m_windowSize.x ) / m_windowSize.x,
|
||||||
zoom * ( m_windowSize.y - 2.0 * aNewMousePosition.y ) / m_windowSize.y );
|
zoom * ( m_windowSize.y - 2.0 * aNewMousePosition.y ) / m_windowSize.y );
|
||||||
|
|
||||||
add_quats( spin_quat, m_quat, m_quat );
|
float spin_matrix[4][4];
|
||||||
|
build_rotmatrix( spin_matrix, spin_quat );
|
||||||
float rotationMatrix[4][4];
|
m_rotationMatrix = glm::make_mat4( &spin_matrix[0][0] ) * m_rotationMatrix;
|
||||||
|
|
||||||
build_rotmatrix( rotationMatrix, m_quat );
|
|
||||||
|
|
||||||
m_rotationMatrix = glm::make_mat4( &rotationMatrix[0][0] );
|
|
||||||
|
|
||||||
updateViewMatrix();
|
updateViewMatrix();
|
||||||
|
|
||||||
updateFrustum();
|
updateFrustum();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TRACK_BALL::SetLookAtPos( const SFVEC3F& aLookAtPos )
|
|
||||||
{
|
|
||||||
if( m_lookat_pos != aLookAtPos )
|
|
||||||
{
|
|
||||||
m_lookat_pos = aLookAtPos;
|
|
||||||
|
|
||||||
updateViewMatrix();
|
|
||||||
updateFrustum();
|
|
||||||
|
|
||||||
m_parametersChanged = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void TRACK_BALL::Pan( const wxPoint& aNewMousePosition )
|
void TRACK_BALL::Pan( const wxPoint& aNewMousePosition )
|
||||||
{
|
{
|
||||||
m_parametersChanged = true;
|
m_parametersChanged = true;
|
||||||
|
@ -106,7 +85,7 @@ void TRACK_BALL::Pan( const wxPoint& aNewMousePosition )
|
||||||
else // PROJECTION_TYPE::PERSPECTIVE
|
else // PROJECTION_TYPE::PERSPECTIVE
|
||||||
{
|
{
|
||||||
// Unproject the coordinates using the precomputed frustum tangent (zoom level dependent)
|
// Unproject the coordinates using the precomputed frustum tangent (zoom level dependent)
|
||||||
const float panFactor = -m_camera_pos.z * m_frustum.tang * 2;
|
const float panFactor = -m_camera_pos.z * m_frustum.tang * 2;
|
||||||
m_camera_pos.x -= panFactor * m_frustum.ratio *
|
m_camera_pos.x -= panFactor * m_frustum.ratio *
|
||||||
( m_lastPosition.x - aNewMousePosition.x ) / m_windowSize.x;
|
( m_lastPosition.x - aNewMousePosition.x ) / m_windowSize.x;
|
||||||
m_camera_pos.y -= panFactor * ( aNewMousePosition.y - m_lastPosition.y ) / m_windowSize.y;
|
m_camera_pos.y -= panFactor * ( aNewMousePosition.y - m_lastPosition.y ) / m_windowSize.y;
|
||||||
|
@ -116,7 +95,6 @@ void TRACK_BALL::Pan( const wxPoint& aNewMousePosition )
|
||||||
updateFrustum();
|
updateFrustum();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TRACK_BALL::Pan( const SFVEC3F& aDeltaOffsetInc )
|
void TRACK_BALL::Pan( const SFVEC3F& aDeltaOffsetInc )
|
||||||
{
|
{
|
||||||
m_parametersChanged = true;
|
m_parametersChanged = true;
|
||||||
|
@ -127,22 +105,11 @@ void TRACK_BALL::Pan( const SFVEC3F& aDeltaOffsetInc )
|
||||||
updateFrustum();
|
updateFrustum();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TRACK_BALL::Pan_T1( const SFVEC3F& aDeltaOffsetInc )
|
void TRACK_BALL::Pan_T1( const SFVEC3F& aDeltaOffsetInc )
|
||||||
{
|
{
|
||||||
m_camera_pos_t1 = m_camera_pos + aDeltaOffsetInc;
|
m_camera_pos_t1 = m_camera_pos + aDeltaOffsetInc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TRACK_BALL::Reset()
|
|
||||||
{
|
|
||||||
CAMERA::Reset();
|
|
||||||
|
|
||||||
memset( m_quat, 0, sizeof( m_quat ) );
|
|
||||||
trackball( m_quat, 0.0, 0.0, 0.0, 0.0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void TRACK_BALL::Reset_T1()
|
void TRACK_BALL::Reset_T1()
|
||||||
{
|
{
|
||||||
CAMERA::Reset_T1();
|
CAMERA::Reset_T1();
|
||||||
|
@ -151,15 +118,19 @@ void TRACK_BALL::Reset_T1()
|
||||||
trackball( m_quat_t1, 0.0, 0.0, 0.0, 0.0 );
|
trackball( m_quat_t1, 0.0, 0.0, 0.0, 0.0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TRACK_BALL::SetT0_and_T1_current_T()
|
void TRACK_BALL::SetT0_and_T1_current_T()
|
||||||
{
|
{
|
||||||
CAMERA::SetT0_and_T1_current_T();
|
CAMERA::SetT0_and_T1_current_T();
|
||||||
|
|
||||||
memcpy( m_quat_t0, m_quat, sizeof( m_quat ) );
|
double quat[4];
|
||||||
memcpy( m_quat_t1, m_quat, sizeof( m_quat ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Charge the quaternions with the current rotation matrix to allow dual input.
|
||||||
|
std::copy_n( glm::value_ptr( glm::conjugate( glm::quat_cast( m_rotationMatrix ) ) ),
|
||||||
|
sizeof( quat ) / sizeof( quat[0] ), quat );
|
||||||
|
|
||||||
|
memcpy( m_quat_t0, quat, sizeof( quat ) );
|
||||||
|
memcpy( m_quat_t1, quat, sizeof( quat ) );
|
||||||
|
}
|
||||||
|
|
||||||
void TRACK_BALL::Interpolate( float t )
|
void TRACK_BALL::Interpolate( float t )
|
||||||
{
|
{
|
||||||
|
@ -184,15 +155,15 @@ void TRACK_BALL::Interpolate( float t )
|
||||||
}
|
}
|
||||||
|
|
||||||
const float t0 = 1.0f - t;
|
const float t0 = 1.0f - t;
|
||||||
|
double quat[4];
|
||||||
m_quat[0] = m_quat_t0[0] * t0 + m_quat_t1[0] * t;
|
quat[0] = m_quat_t0[0] * t0 + m_quat_t1[0] * t;
|
||||||
m_quat[1] = m_quat_t0[1] * t0 + m_quat_t1[1] * t;
|
quat[1] = m_quat_t0[1] * t0 + m_quat_t1[1] * t;
|
||||||
m_quat[2] = m_quat_t0[2] * t0 + m_quat_t1[2] * t;
|
quat[2] = m_quat_t0[2] * t0 + m_quat_t1[2] * t;
|
||||||
m_quat[3] = m_quat_t0[3] * t0 + m_quat_t1[3] * t;
|
quat[3] = m_quat_t0[3] * t0 + m_quat_t1[3] * t;
|
||||||
|
|
||||||
float rotationMatrix[4][4];
|
float rotationMatrix[4][4];
|
||||||
|
|
||||||
build_rotmatrix( rotationMatrix, m_quat );
|
build_rotmatrix( rotationMatrix, quat );
|
||||||
|
|
||||||
m_rotationMatrix = glm::make_mat4( &rotationMatrix[0][0] );
|
m_rotationMatrix = glm::make_mat4( &rotationMatrix[0][0] );
|
||||||
|
|
||||||
|
|
|
@ -50,10 +50,6 @@ public:
|
||||||
|
|
||||||
void Pan_T1( const SFVEC3F& aDeltaOffsetInc ) override;
|
void Pan_T1( const SFVEC3F& aDeltaOffsetInc ) override;
|
||||||
|
|
||||||
void SetLookAtPos( const SFVEC3F& aLookAtPos ) override;
|
|
||||||
|
|
||||||
void Reset() override;
|
|
||||||
|
|
||||||
void Reset_T1() override;
|
void Reset_T1() override;
|
||||||
|
|
||||||
void SetT0_and_T1_current_T() override;
|
void SetT0_and_T1_current_T() override;
|
||||||
|
@ -62,9 +58,8 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* quarternion of the trackball
|
* interpolate quaternions of the trackball
|
||||||
*/
|
*/
|
||||||
double m_quat[4];
|
|
||||||
double m_quat_t0[4];
|
double m_quat_t0[4];
|
||||||
double m_quat_t1[4];
|
double m_quat_t1[4];
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue