mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-09-14 10:13:19 +02:00
Rotating to 0 when above pi would result in the board spinning back through pi to get there. This led to jarring motion. Also fix an issue added in b6f64815 where the board would rotate 2pi when crossing over the 0-2pi boundary. (Cherry-pick of 4fc9b4e5ab63fa192ec2a7d40574f614b318668c)
605 lines
17 KiB
C++
605 lines
17 KiB
C++
/*
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
*
|
|
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
|
* Copyright (C) 1992-2019 KiCad Developers, see AUTHORS.txt for contributors.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, you may find one here:
|
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
|
* or you may write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
|
|
/**
|
|
* @file ccamera.cpp
|
|
* @brief
|
|
*/
|
|
|
|
#include "ccamera.h"
|
|
#include <wx/log.h>
|
|
|
|
|
|
// A helper function to normalize aAngle between -2PI and +2PI
|
|
inline void normalise2PI( float& aAngle )
|
|
{
|
|
while( aAngle > 0.0 )
|
|
aAngle -= M_PI*2;
|
|
|
|
while( aAngle < 0.0 )
|
|
aAngle += M_PI*2;
|
|
}
|
|
|
|
|
|
/**
|
|
* Trace mask used to enable or disable the trace output of this class.
|
|
* The debug output can be turned on by setting the WXTRACE environment variable to
|
|
* "KI_TRACE_CCAMERA". See the wxWidgets documentation on wxLogTrace for
|
|
* more information.
|
|
*/
|
|
const wxChar *CCAMERA::m_logTrace = wxT( "KI_TRACE_CCAMERA" );
|
|
|
|
#define MIN_ZOOM 0.10f
|
|
#define MAX_ZOOM 1.25f
|
|
|
|
CCAMERA::CCAMERA( float aRangeScale )
|
|
{
|
|
wxLogTrace( m_logTrace, wxT( "CCAMERA::CCAMERA" ) );
|
|
|
|
m_range_scale = aRangeScale;
|
|
m_camera_pos_init = SFVEC3F( 0.0f, 0.0f, -(aRangeScale * 2.0f ) );
|
|
m_board_lookat_pos_init = SFVEC3F( 0.0f );
|
|
m_windowSize = SFVEC2I( 0, 0 );
|
|
m_projectionType = PROJECTION_PERSPECTIVE;
|
|
m_interpolation_mode = INTERPOLATION_BEZIER;
|
|
|
|
Reset();
|
|
}
|
|
|
|
|
|
void CCAMERA::Reset()
|
|
{
|
|
m_parametersChanged = true;
|
|
m_projectionMatrix = glm::mat4( 1.0f );
|
|
m_projectionMatrixInv = glm::mat4( 1.0f );
|
|
m_rotationMatrix = glm::mat4( 1.0f );
|
|
m_rotationMatrixAux = glm::mat4( 1.0f );
|
|
m_lastPosition = wxPoint( 0, 0 );
|
|
|
|
m_zoom = 1.0f;
|
|
m_zoom_t0 = 1.0f;
|
|
m_zoom_t1 = 1.0f;
|
|
m_camera_pos = m_camera_pos_init;
|
|
m_camera_pos_t0 = m_camera_pos_init;
|
|
m_camera_pos_t1 = m_camera_pos_init;
|
|
m_lookat_pos = m_board_lookat_pos_init;
|
|
m_lookat_pos_t0 = m_board_lookat_pos_init;
|
|
m_lookat_pos_t1 = m_board_lookat_pos_init;
|
|
|
|
m_rotate_aux = SFVEC3F( 0.0f );
|
|
m_rotate_aux_t0 = SFVEC3F( 0.0f );
|
|
m_rotate_aux_t1 = SFVEC3F( 0.0f );
|
|
|
|
updateRotationMatrix();
|
|
updateViewMatrix();
|
|
m_viewMatrixInverse = glm::inverse( m_viewMatrix );
|
|
m_scr_nX.clear();
|
|
m_scr_nY.clear();
|
|
rebuildProjection();
|
|
}
|
|
|
|
|
|
void CCAMERA::Reset_T1()
|
|
{
|
|
m_camera_pos_t1 = m_camera_pos_init;
|
|
m_zoom_t1 = 1.0f;
|
|
m_rotate_aux_t1 = SFVEC3F( 0.0f );
|
|
m_lookat_pos_t1 = m_board_lookat_pos_init;
|
|
|
|
|
|
// Since 0 = 2pi, we want to reset the angle to be the closest
|
|
// one to where we currently are. That ensures that we rotate
|
|
// the board around the smallest distance getting there.
|
|
if( m_rotate_aux_t0.x > M_PI )
|
|
m_rotate_aux_t1.x = 2*M_PI;
|
|
|
|
if( m_rotate_aux_t0.y > M_PI )
|
|
m_rotate_aux_t1.y = 2*M_PI;
|
|
|
|
if( m_rotate_aux_t0.z > M_PI )
|
|
m_rotate_aux_t1.z = 2*M_PI;
|
|
|
|
}
|
|
|
|
|
|
void CCAMERA::updateViewMatrix()
|
|
{
|
|
m_viewMatrix = glm::translate( glm::mat4( 1.0f ), m_camera_pos ) *
|
|
m_rotationMatrix * m_rotationMatrixAux *
|
|
glm::translate( glm::mat4( 1.0f ), -m_lookat_pos );
|
|
}
|
|
|
|
|
|
void CCAMERA::updateRotationMatrix()
|
|
{
|
|
m_rotationMatrixAux = glm::rotate( glm::mat4( 1.0f ),
|
|
m_rotate_aux.x,
|
|
SFVEC3F( 1.0f, 0.0f, 0.0f ) );
|
|
normalise2PI( m_rotate_aux.x );
|
|
|
|
m_rotationMatrixAux = glm::rotate( m_rotationMatrixAux,
|
|
m_rotate_aux.y,
|
|
SFVEC3F( 0.0f, 1.0f, 0.0f ) );
|
|
normalise2PI( m_rotate_aux.y );
|
|
|
|
m_rotationMatrixAux = glm::rotate( m_rotationMatrixAux,
|
|
m_rotate_aux.z,
|
|
SFVEC3F( 0.0f, 0.0f, 1.0f ) );
|
|
normalise2PI( m_rotate_aux.z );
|
|
|
|
m_parametersChanged = true;
|
|
|
|
updateViewMatrix();
|
|
updateFrustum();
|
|
}
|
|
|
|
|
|
const glm::mat4 CCAMERA::GetRotationMatrix() const
|
|
{
|
|
return m_rotationMatrix * m_rotationMatrixAux;
|
|
}
|
|
|
|
|
|
void CCAMERA::rebuildProjection()
|
|
{
|
|
if( (m_windowSize.x == 0) ||
|
|
(m_windowSize.y == 0) )
|
|
return;
|
|
|
|
m_frustum.ratio = (float) m_windowSize.x / (float)m_windowSize.y;
|
|
|
|
// Consider that we can render double the length multiplied by the 2/sqrt(2)
|
|
//
|
|
m_frustum.farD = glm::length( m_camera_pos_init ) * 2.0f * ( 2.0f * sqrtf( 2.0f ) );
|
|
|
|
switch( m_projectionType )
|
|
{
|
|
default:
|
|
case PROJECTION_PERSPECTIVE:
|
|
|
|
m_frustum.nearD = 0.10f;
|
|
|
|
// Ratio width / height of the window display
|
|
m_frustum.angle = 45.0f * m_zoom;
|
|
|
|
|
|
m_projectionMatrix = glm::perspective( glm::radians( m_frustum.angle ),
|
|
m_frustum.ratio,
|
|
m_frustum.nearD,
|
|
m_frustum.farD );
|
|
|
|
m_projectionMatrixInv = glm::inverse( m_projectionMatrix );
|
|
|
|
m_frustum.tang = glm::tan( glm::radians( m_frustum.angle ) * 0.5f );
|
|
|
|
m_focalLen.x = ( (float)m_windowSize.y / (float)m_windowSize.x ) / m_frustum.tang;
|
|
m_focalLen.y = 1.0f / m_frustum.tang;
|
|
|
|
m_frustum.nh = m_frustum.nearD * m_frustum.tang;
|
|
m_frustum.nw = m_frustum.nh * m_frustum.ratio;
|
|
m_frustum.fh = m_frustum.farD * m_frustum.tang;
|
|
m_frustum.fw = m_frustum.fh * m_frustum.ratio;
|
|
break;
|
|
|
|
case PROJECTION_ORTHO:
|
|
|
|
m_frustum.nearD = -m_frustum.farD; // Use a symmetrical clip plane for ortho projection
|
|
|
|
// This formula was found by trial and error
|
|
const float orthoReductionFactor = glm::length( m_camera_pos_init ) *
|
|
m_zoom * m_zoom * 0.5f;
|
|
|
|
// Initialize Projection Matrix for Ortographic View
|
|
m_projectionMatrix = glm::ortho( -m_frustum.ratio * orthoReductionFactor,
|
|
m_frustum.ratio * orthoReductionFactor,
|
|
-orthoReductionFactor,
|
|
orthoReductionFactor,
|
|
m_frustum.nearD, m_frustum.farD );
|
|
|
|
m_projectionMatrixInv = glm::inverse( m_projectionMatrix );
|
|
|
|
m_frustum.nw = orthoReductionFactor * 2.0f * m_frustum.ratio;
|
|
m_frustum.nh = orthoReductionFactor * 2.0f;
|
|
m_frustum.fw = m_frustum.nw;
|
|
m_frustum.fh = m_frustum.nh;
|
|
|
|
break;
|
|
}
|
|
|
|
if ( (m_windowSize.x > 0) &&
|
|
(m_windowSize.y > 0) )
|
|
{
|
|
m_scr_nX.resize( m_windowSize.x + 1 );
|
|
m_scr_nY.resize( m_windowSize.y + 1 );
|
|
|
|
// Precalc X values for camera -> ray generation
|
|
for( unsigned int x = 0; x < (unsigned int)m_windowSize.x + 1; ++x )
|
|
{
|
|
// Converts 0.0 .. 1.0
|
|
const float xNormalizedDeviceCoordinates = ( ( (float)x + 0.5f ) /
|
|
(m_windowSize.x - 0.0f) );
|
|
|
|
// Converts -1.0 .. 1.0
|
|
m_scr_nX[x] = 2.0f * xNormalizedDeviceCoordinates - 1.0f;
|
|
}
|
|
|
|
// Precalc Y values for camera -> ray generation
|
|
for( unsigned int y = 0; y < (unsigned int)m_windowSize.y + 1 ; ++y )
|
|
{
|
|
// Converts 0.0 .. 1.0
|
|
const float yNormalizedDeviceCoordinates = ( ( (float)y + 0.5f ) /
|
|
(m_windowSize.y - 0.0f) );
|
|
|
|
// Converts -1.0 .. 1.0
|
|
m_scr_nY[y] = 2.0f * yNormalizedDeviceCoordinates - 1.0f;
|
|
}
|
|
|
|
updateFrustum();
|
|
}
|
|
}
|
|
|
|
|
|
void CCAMERA::updateFrustum()
|
|
{
|
|
// Update matrix and vectors
|
|
m_viewMatrixInverse = glm::inverse( m_viewMatrix );
|
|
|
|
m_right = glm::normalize( SFVEC3F( m_viewMatrixInverse *
|
|
glm::vec4( SFVEC3F( 1.0, 0.0, 0.0 ), 0.0 ) ) );
|
|
|
|
m_up = glm::normalize( SFVEC3F( m_viewMatrixInverse *
|
|
glm::vec4( SFVEC3F( 0.0, 1.0, 0.0 ), 0.0 ) ) );
|
|
|
|
m_dir = glm::normalize( SFVEC3F( m_viewMatrixInverse *
|
|
glm::vec4( SFVEC3F( 0.0, 0.0, 1.0 ), 0.0 ) ) );
|
|
|
|
m_pos = SFVEC3F( m_viewMatrixInverse * glm::vec4( SFVEC3F( 0.0, 0.0, 0.0 ), 1.0 ) );
|
|
|
|
|
|
/*
|
|
* Frustum is a implementation based on a tutorial by
|
|
* http://www.lighthouse3d.com/tutorials/view-frustum-culling/
|
|
*/
|
|
|
|
// compute the centers of the near and far planes
|
|
m_frustum.nc = m_pos - m_dir * m_frustum.nearD;
|
|
m_frustum.fc = m_pos - m_dir * m_frustum.farD;
|
|
|
|
// compute the 4 corners of the frustum on the near plane
|
|
m_frustum.ntl = m_frustum.nc + m_up * m_frustum.nh - m_right * m_frustum.nw;
|
|
m_frustum.ntr = m_frustum.nc + m_up * m_frustum.nh + m_right * m_frustum.nw;
|
|
m_frustum.nbl = m_frustum.nc - m_up * m_frustum.nh - m_right * m_frustum.nw;
|
|
m_frustum.nbr = m_frustum.nc - m_up * m_frustum.nh + m_right * m_frustum.nw;
|
|
|
|
// compute the 4 corners of the frustum on the far plane
|
|
m_frustum.ftl = m_frustum.fc + m_up * m_frustum.fh - m_right * m_frustum.fw;
|
|
m_frustum.ftr = m_frustum.fc + m_up * m_frustum.fh + m_right * m_frustum.fw;
|
|
m_frustum.fbl = m_frustum.fc - m_up * m_frustum.fh - m_right * m_frustum.fw;
|
|
m_frustum.fbr = m_frustum.fc - m_up * m_frustum.fh + m_right * m_frustum.fw;
|
|
|
|
if ( (m_windowSize.x > 0) &&
|
|
(m_windowSize.y > 0) )
|
|
{
|
|
// Reserve size for precalc values
|
|
m_right_nX.resize( m_windowSize.x + 1 );
|
|
m_up_nY.resize( m_windowSize.y + 1 );
|
|
|
|
// Precalc X values for camera -> ray generation
|
|
const SFVEC3F right_nw = m_right * m_frustum.nw;
|
|
|
|
for( unsigned int x = 0; x < ((unsigned int)m_windowSize.x + 1); ++x )
|
|
m_right_nX[x] = right_nw * m_scr_nX[x];
|
|
|
|
// Precalc Y values for camera -> ray generation
|
|
const SFVEC3F up_nh = m_up * m_frustum.nh;
|
|
|
|
for( unsigned int y = 0; y < ((unsigned int)m_windowSize.y + 1); ++y )
|
|
m_up_nY[y] = up_nh * m_scr_nY[y];
|
|
}
|
|
}
|
|
|
|
|
|
void CCAMERA::MakeRay( const SFVEC2I &aWindowPos,
|
|
SFVEC3F &aOutOrigin,
|
|
SFVEC3F &aOutDirection ) const
|
|
{
|
|
wxASSERT( aWindowPos.x < m_windowSize.x );
|
|
wxASSERT( aWindowPos.y < m_windowSize.y );
|
|
|
|
const SFVEC3F up_plus_right = m_up_nY[aWindowPos.y] +
|
|
m_right_nX[aWindowPos.x];
|
|
|
|
switch( m_projectionType )
|
|
{
|
|
default:
|
|
case PROJECTION_PERSPECTIVE:
|
|
aOutOrigin = up_plus_right + m_frustum.nc;
|
|
aOutDirection = glm::normalize( aOutOrigin - m_pos );
|
|
break;
|
|
|
|
case PROJECTION_ORTHO:
|
|
aOutOrigin = up_plus_right * 0.5f + m_frustum.nc;
|
|
aOutDirection = -m_dir + SFVEC3F( FLT_EPSILON );
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
void CCAMERA::MakeRay( const SFVEC2F &aWindowPos, SFVEC3F &aOutOrigin, SFVEC3F &aOutDirection ) const
|
|
{
|
|
wxASSERT( aWindowPos.x < (float)m_windowSize.x );
|
|
wxASSERT( aWindowPos.y < (float)m_windowSize.y );
|
|
|
|
const SFVEC2F floorWinPos_f = glm::floor( aWindowPos );
|
|
const SFVEC2I floorWinPos_i = (SFVEC2I)floorWinPos_f;
|
|
const SFVEC2F relativeWinPos = aWindowPos - floorWinPos_f;
|
|
|
|
// Note: size of vectors m_up and m_right are m_windowSize + 1
|
|
const SFVEC3F up_plus_right = m_up_nY[floorWinPos_i.y] * (1.0f - relativeWinPos.y) +
|
|
m_up_nY[floorWinPos_i.y + 1] * relativeWinPos.y +
|
|
m_right_nX[floorWinPos_i.x] * (1.0f - relativeWinPos.x) +
|
|
m_right_nX[floorWinPos_i.x + 1] * relativeWinPos.x;
|
|
|
|
switch( m_projectionType )
|
|
{
|
|
default:
|
|
case PROJECTION_PERSPECTIVE:
|
|
aOutOrigin = up_plus_right + m_frustum.nc;
|
|
aOutDirection = glm::normalize( aOutOrigin - m_pos );
|
|
break;
|
|
|
|
case PROJECTION_ORTHO:
|
|
aOutOrigin = up_plus_right * 0.5f + m_frustum.nc;
|
|
aOutDirection = -m_dir + SFVEC3F( FLT_EPSILON );
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
void CCAMERA::MakeRayAtCurrrentMousePosition( SFVEC3F &aOutOrigin,
|
|
SFVEC3F &aOutDirection ) const
|
|
{
|
|
MakeRay( SFVEC2I( m_lastPosition.x,
|
|
m_windowSize.y - m_lastPosition.y ),
|
|
aOutOrigin, aOutDirection );
|
|
}
|
|
|
|
|
|
const glm::mat4 &CCAMERA::GetProjectionMatrix() const
|
|
{
|
|
return m_projectionMatrix;
|
|
}
|
|
|
|
|
|
const glm::mat4 &CCAMERA::GetProjectionMatrixInv() const
|
|
{
|
|
return m_projectionMatrixInv;
|
|
}
|
|
|
|
|
|
void CCAMERA::ResetXYpos()
|
|
{
|
|
m_parametersChanged = true;
|
|
m_camera_pos.x = 0.0f;
|
|
m_camera_pos.y = 0.0f;
|
|
|
|
updateViewMatrix();
|
|
updateFrustum();
|
|
}
|
|
|
|
|
|
void CCAMERA::ResetXYpos_T1()
|
|
{
|
|
m_camera_pos_t1.x = 0.0f;
|
|
m_camera_pos_t1.y = 0.0f;
|
|
}
|
|
|
|
|
|
const glm::mat4 &CCAMERA::GetViewMatrix() const
|
|
{
|
|
return m_viewMatrix;
|
|
}
|
|
|
|
|
|
const glm::mat4 &CCAMERA::GetViewMatrix_Inv() const
|
|
{
|
|
return m_viewMatrixInverse;
|
|
}
|
|
|
|
|
|
void CCAMERA::SetCurMousePosition( const wxPoint &aNewMousePosition )
|
|
{
|
|
m_lastPosition = aNewMousePosition;
|
|
}
|
|
|
|
|
|
void CCAMERA::SetProjection( PROJECTION_TYPE aProjectionType )
|
|
{
|
|
if( m_projectionType != aProjectionType )
|
|
{
|
|
m_projectionType = aProjectionType;
|
|
rebuildProjection();
|
|
}
|
|
}
|
|
|
|
|
|
void CCAMERA::ToggleProjection()
|
|
{
|
|
if( m_projectionType == PROJECTION_ORTHO )
|
|
m_projectionType = PROJECTION_PERSPECTIVE;
|
|
else
|
|
m_projectionType = PROJECTION_ORTHO;
|
|
|
|
rebuildProjection();
|
|
}
|
|
|
|
|
|
bool CCAMERA::SetCurWindowSize( const wxSize &aSize )
|
|
{
|
|
const SFVEC2I newSize = SFVEC2I( aSize.x, aSize.y );
|
|
|
|
if( m_windowSize != newSize )
|
|
{
|
|
m_windowSize = newSize;
|
|
rebuildProjection();
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
void CCAMERA::ZoomReset()
|
|
{
|
|
m_zoom = 1.0f;
|
|
|
|
m_camera_pos.z = m_camera_pos_init.z;
|
|
|
|
updateViewMatrix();
|
|
rebuildProjection();
|
|
}
|
|
|
|
bool CCAMERA::Zoom( float aFactor )
|
|
{
|
|
if ( ( m_zoom == MIN_ZOOM && aFactor > 1 ) || ( m_zoom == MAX_ZOOM && aFactor < 1 ) || aFactor == 1 )
|
|
return false;
|
|
|
|
m_zoom /= aFactor;
|
|
if( m_zoom <= MIN_ZOOM )
|
|
m_zoom = MIN_ZOOM;
|
|
if( m_zoom >= MAX_ZOOM )
|
|
m_zoom = MAX_ZOOM;
|
|
|
|
m_camera_pos.z = m_camera_pos_init.z * m_zoom;
|
|
|
|
updateViewMatrix();
|
|
rebuildProjection();
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CCAMERA::Zoom_T1( float aFactor )
|
|
{
|
|
if( ( m_zoom == MIN_ZOOM && aFactor > 1 ) || ( m_zoom == MAX_ZOOM && aFactor < 1 ) || aFactor == 1 )
|
|
return false;
|
|
|
|
m_zoom_t1 = m_zoom / aFactor;
|
|
if (m_zoom_t1 < MIN_ZOOM )
|
|
m_zoom_t1 = MIN_ZOOM;
|
|
if (m_zoom_t1 > MAX_ZOOM )
|
|
m_zoom_t1 = MAX_ZOOM;
|
|
|
|
m_camera_pos_t1.z = m_camera_pos_init.z * m_zoom_t1;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
float CCAMERA::ZoomGet() const
|
|
{
|
|
return m_zoom;
|
|
}
|
|
|
|
|
|
void CCAMERA::RotateX( float aAngleInRadians )
|
|
{
|
|
m_rotate_aux.x += aAngleInRadians;
|
|
updateRotationMatrix();
|
|
}
|
|
|
|
|
|
void CCAMERA::RotateY( float aAngleInRadians )
|
|
{
|
|
m_rotate_aux.y += aAngleInRadians;
|
|
updateRotationMatrix();
|
|
}
|
|
|
|
|
|
void CCAMERA::RotateZ( float aAngleInRadians )
|
|
{
|
|
m_rotate_aux.z += aAngleInRadians;
|
|
updateRotationMatrix();
|
|
}
|
|
|
|
|
|
void CCAMERA::RotateX_T1( float aAngleInRadians )
|
|
{
|
|
m_rotate_aux_t1.x += aAngleInRadians;
|
|
}
|
|
|
|
|
|
void CCAMERA::RotateY_T1( float aAngleInRadians )
|
|
{
|
|
m_rotate_aux_t1.y += aAngleInRadians;
|
|
}
|
|
|
|
|
|
void CCAMERA::RotateZ_T1( float aAngleInRadians )
|
|
{
|
|
m_rotate_aux_t1.z += aAngleInRadians;
|
|
}
|
|
|
|
|
|
void CCAMERA::SetT0_and_T1_current_T()
|
|
{
|
|
m_camera_pos_t0 = m_camera_pos;
|
|
m_lookat_pos_t0 = m_lookat_pos;
|
|
m_rotate_aux_t0 = m_rotate_aux;
|
|
m_zoom_t0 = m_zoom;
|
|
|
|
m_camera_pos_t1 = m_camera_pos;
|
|
m_lookat_pos_t1 = m_lookat_pos;
|
|
m_rotate_aux_t1 = m_rotate_aux;
|
|
m_zoom_t1 = m_zoom;
|
|
}
|
|
|
|
|
|
void CCAMERA::Interpolate( float t )
|
|
{
|
|
wxASSERT( t >= 0.0f );
|
|
|
|
const float t0 = 1.0f - t;
|
|
|
|
m_camera_pos = m_camera_pos_t0 * t0 + m_camera_pos_t1 * t;
|
|
m_lookat_pos = m_lookat_pos_t0 * t0 + m_lookat_pos_t1 * t;
|
|
m_rotate_aux = m_rotate_aux_t0 * t0 + m_rotate_aux_t1 * t;
|
|
m_zoom = m_zoom_t0 * t0 + m_zoom_t1 * t;
|
|
|
|
m_parametersChanged = true;
|
|
|
|
updateRotationMatrix();
|
|
rebuildProjection();
|
|
}
|
|
|
|
|
|
bool CCAMERA::ParametersChanged()
|
|
{
|
|
const bool parametersChanged = m_parametersChanged;
|
|
|
|
m_parametersChanged = false;
|
|
|
|
return parametersChanged;
|
|
}
|