17 #if defined( _MSC_VER )
18 # pragma warning( disable : 4127 )
19 #elif defined( __clang__ )
20 # if ( 10 <= __clang_major__ )
21 # pragma clang diagnostic ignored "-Wdeprecated-volatile"
23 #elif defined( __GNUC__ )
31 #include <glm/glm.hpp>
32 #include <glm/gtx/rotate_vector.hpp>
46 return fabs( _a ) < std::numeric_limits<T>::epsilon();
51 return areEqual( _a, (T)1 );
53 inline float sign(
float s )
55 return ( s < 0.f ) ? -1.f : 1.f;
65 return m_cameraPosition;
70 return m_centerPosition;
85 return m_mousePosition;
111 switch ( mouseButton )
133 default: assert(
false );
136 motion( position, curAction );
143 m_cameraPosition = cameraPosition;
144 m_centerPosition = centerPosition;
145 m_upVector = upVector;
156 m_mousePosition = position;
177 float fValue =
static_cast<float>( value );
178 float dx = ( fValue * std::abs( fValue ) ) /
static_cast<float>( m_windowSize[0] );
180 glm::vec3 z = m_cameraPosition - m_centerPosition;
181 float length = z.length() * 0.1f;
182 length = length < 0.001f ? 0.001f : length;
185 dolly( glm::vec2( dx, dx ) );
189 void CameraManipulator::dolly( glm::vec2
const & delta )
191 glm::vec3 z = m_centerPosition - m_cameraPosition;
192 float length = glm::length( z );
208 dd = fabs( delta[0] ) > fabs( delta[1] ) ? delta[0] : -delta[1];
211 float factor = m_speed * dd / length;
215 length = length < 0.001f ? 0.001f : length;
219 if ( 1.0f <= factor )
229 if ( m_upVector.y > m_upVector.z )
239 m_cameraPosition += z;
244 m_centerPosition += z;
248 void CameraManipulator::motion( glm::ivec2
const & position, Action action )
250 glm::vec2 delta(
float( position[0] - m_mousePosition[0] ) /
float( m_windowSize[0] ),
251 float( position[1] - m_mousePosition[1] ) /
float( m_windowSize[1] ) );
258 orbit( delta,
true );
262 orbit( delta,
false );
270 trackball( position );
274 orbit( glm::vec2( delta[0], -delta[1] ),
true );
282 m_mousePosition = position;
285 void CameraManipulator::orbit( glm::vec2
const & delta,
bool invert )
293 float dx = delta[0] * float( glm::two_pi<float>() );
294 float dy = delta[1] * float( glm::two_pi<float>() );
297 glm::vec3 origin( invert ? m_cameraPosition : m_centerPosition );
298 glm::vec3 position( invert ? m_centerPosition : m_cameraPosition );
301 glm::vec3 centerToEye( position - origin );
302 float radius = glm::length( centerToEye );
303 centerToEye = glm::normalize( centerToEye );
306 glm::vec3 zAxis( centerToEye );
307 glm::mat4 yRotation = glm::rotate( -dx, m_upVector );
310 glm::vec4 tmpVector = yRotation * glm::vec4( centerToEye.x, centerToEye.y, centerToEye.z, 0.0f );
311 centerToEye = glm::vec3( tmpVector.x, tmpVector.y, tmpVector.z );
314 glm::vec3 xAxis = glm::cross( m_upVector, zAxis );
315 xAxis = glm::normalize( xAxis );
316 glm::mat4 xRotation = glm::rotate( -dy, xAxis );
319 tmpVector = xRotation * glm::vec4( centerToEye.x, centerToEye.y, centerToEye.z, 0 );
320 glm::vec3 rotatedVector( tmpVector.x, tmpVector.y, tmpVector.z );
321 if (
sign( rotatedVector.x ) ==
sign( centerToEye.x ) )
323 centerToEye = rotatedVector;
327 centerToEye *= radius;
330 glm::vec3 newPosition = centerToEye + origin;
334 m_cameraPosition = newPosition;
338 m_centerPosition = newPosition;
342 void CameraManipulator::pan( glm::vec2
const & delta )
344 glm::vec3 z( m_cameraPosition - m_centerPosition );
345 float length =
static_cast<float>( glm::length( z ) ) / 0.785f;
346 z = glm::normalize( z );
347 glm::vec3 x = glm::normalize( glm::cross( m_upVector, z ) );
348 glm::vec3 y = glm::normalize( glm::cross( z, x ) );
349 x *= -delta[0] * length;
350 y *= delta[1] * length;
358 m_cameraPosition += x + y;
359 m_centerPosition += x + y;
362 double CameraManipulator::projectOntoTBSphere(
const glm::vec2 & p )
365 double d = length( p );
381 void CameraManipulator::trackball( glm::ivec2
const & position )
383 glm::vec2 p0( 2 * ( m_mousePosition[0] - m_windowSize[0] / 2 ) /
double( m_windowSize[0] ),
384 2 * ( m_windowSize[1] / 2 - m_mousePosition[1] ) /
double( m_windowSize[1] ) );
385 glm::vec2 p1( 2 * ( position[0] - m_windowSize[0] / 2 ) /
double( m_windowSize[0] ),
386 2 * ( m_windowSize[1] / 2 - position[1] ) /
double( m_windowSize[1] ) );
389 glm::vec3 pTB0( p0[0], p0[1], projectOntoTBSphere( p0 ) );
390 glm::vec3 pTB1( p1[0], p1[1], projectOntoTBSphere( p1 ) );
393 glm::vec3 axis = glm::cross( pTB0, pTB1 );
394 axis = glm::normalize( axis );
397 float t = glm::length( pTB0 - pTB1 ) / ( 2.f *
trackballSize );
404 else if ( t < -1.0f )
409 float rad = 2.0f * asin( t );
412 glm::vec4 rot_axis = m_matrix * glm::vec4( axis, 0 );
413 glm::mat4 rot_mat = glm::rotate( rad, glm::vec3( rot_axis.x, rot_axis.y, rot_axis.z ) );
415 glm::vec3 pnt = m_cameraPosition - m_centerPosition;
416 glm::vec4 pnt2 = rot_mat * glm::vec4( pnt.x, pnt.y, pnt.z, 1 );
417 m_cameraPosition = m_centerPosition + glm::vec3( pnt2.x, pnt2.y, pnt2.z );
418 glm::vec4 up2 = rot_mat * glm::vec4( m_upVector.x, m_upVector.y, m_upVector.z, 0 );
419 m_upVector = glm::vec3( up2.x, up2.y, up2.z );
423 void CameraManipulator::update()
425 m_matrix = glm::lookAt( m_cameraPosition, m_centerPosition, m_upVector );
429 glm::mat4 rot = glm::rotate( m_roll, glm::vec3( 0, 0, 1 ) );
430 m_matrix = m_matrix * rot;
Action mouseMove(glm::ivec2 const &position, MouseButton mouseButton, ModifierFlags &modifiers)
void setMousePosition(glm::ivec2 const &position)
glm::mat4 const & getMatrix() const
glm::vec3 const & getCameraPosition() const
void setLookat(const glm::vec3 &cameraPosition, const glm::vec3 ¢erPosition, const glm::vec3 &upVector)
glm::vec3 const & getUpVector() const
void setWindowSize(glm::ivec2 const &size)
glm::u32vec2 const & getWindowSize() const
void setSpeed(float speed)
glm::ivec2 const & getMousePosition() const
glm::vec3 const & getCenterPosition() const
const float trackballSize