401b66cc0e
- aggiunto comando TSC ShowMode - correzione a GetCamera.
348 lines
10 KiB
C++
348 lines
10 KiB
C++
//----------------------------------------------------------------------------
|
|
// EgalTech 2013-2014
|
|
//----------------------------------------------------------------------------
|
|
// File : SceneCamera.cpp Data : 10.02.14 Versione : 1.5b1
|
|
// Contenuto : Implementazione della gestione camera della classe scena.
|
|
//
|
|
//
|
|
//
|
|
// Modifiche : 10.02.14 DS Creazione modulo.
|
|
//
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
//--------------------------- Include ----------------------------------------
|
|
#include "stdafx.h"
|
|
#include "Scene.h"
|
|
#include "/EgtDev/Include/EgtILogger.h"
|
|
#include "/EgtDev/Include/EGnStringUtils.h"
|
|
#include "/EgtDev/Include/EGkFrame3d.h"
|
|
|
|
using namespace std ;
|
|
|
|
//--------------------------- Constants --------------------------------------
|
|
static const double MIN_DIST_CAMERA = 10 ;
|
|
static const double STD_DIST_CAMERA = 1000 ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Scene::SetCenter( const Point3d& ptCenter)
|
|
{
|
|
// assegno il punto
|
|
m_ptCenter = ptCenter ;
|
|
// invalido ExtView
|
|
m_bExtViewOk = false ;
|
|
// calcolo nuovi dati di Z clipping
|
|
CalcClippingPlanesFromExtView() ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Scene::SetCamera( double dAngVertDeg, double dAngOrizzDeg, double dDist)
|
|
{
|
|
// assegno la direzione e la distanza
|
|
m_vtDirCamera.FromSpherical( 1, dAngVertDeg, dAngOrizzDeg) ;
|
|
m_dDistCamera = dDist ;
|
|
return VerifyCamera() ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Scene::SetCamera( int nDir, double dDist)
|
|
{
|
|
switch ( nDir) {
|
|
case CT_TOP :
|
|
m_vtDirCamera.Set( 0, 0, 1) ;
|
|
break ;
|
|
case CT_FRONT :
|
|
m_vtDirCamera.Set( 0, -1, 0) ;
|
|
break ;
|
|
case CT_RIGHT :
|
|
m_vtDirCamera.Set( 1, 0, 0) ;
|
|
break ;
|
|
case CT_BACK :
|
|
m_vtDirCamera.Set( 0, 1, 0) ;
|
|
break ;
|
|
case CT_LEFT :
|
|
m_vtDirCamera.Set( -1, 0, 0) ;
|
|
break ;
|
|
case CT_BOTTOM :
|
|
m_vtDirCamera.Set( 0, 0, -1) ;
|
|
break ;
|
|
case CT_ISO_SW :
|
|
m_vtDirCamera.Set( - SQRT1_3, - SQRT1_3, SQRT1_3) ;
|
|
break ;
|
|
case CT_ISO_SE :
|
|
m_vtDirCamera.Set( SQRT1_3, - SQRT1_3, SQRT1_3) ;
|
|
break ;
|
|
case CT_ISO_NE :
|
|
m_vtDirCamera.Set( SQRT1_3, SQRT1_3, SQRT1_3) ;
|
|
break ;
|
|
case CT_ISO_NW :
|
|
m_vtDirCamera.Set( - SQRT1_3, SQRT1_3, SQRT1_3) ;
|
|
break ;
|
|
default :
|
|
return false ;
|
|
break ;
|
|
}
|
|
m_dDistCamera = dDist ;
|
|
|
|
return VerifyCamera() ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Scene::VerifyCamera( void)
|
|
{
|
|
// verifico il versore
|
|
if ( ! m_vtDirCamera.Normalize())
|
|
m_vtDirCamera.Set( 0, 0, 1) ;
|
|
// verifico la distanza
|
|
if ( m_dDistCamera < EPS_SMALL)
|
|
m_dDistCamera = STD_DIST_CAMERA ;
|
|
else
|
|
m_dDistCamera = __max( m_dDistCamera, MIN_DIST_CAMERA) ;
|
|
// invalido Up e ExtView
|
|
m_bUpOk = false ;
|
|
m_bExtViewOk = false ;
|
|
// calcolo nuovi dati di Z clipping
|
|
CalcClippingPlanesFromExtView() ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void
|
|
Scene::GetCamera( double* pdAngVertDeg, double* pdAngOrizzDeg, double* pdDist)
|
|
{
|
|
double dAngVertDeg ;
|
|
double dAngOrizzDeg ;
|
|
m_vtDirCamera.ToSpherical( nullptr, &dAngVertDeg, &dAngOrizzDeg) ;
|
|
if ( fabs( dAngVertDeg) < EPS_ANG_SMALL)
|
|
dAngOrizzDeg = -90 ;
|
|
if ( pdAngVertDeg != nullptr)
|
|
*pdAngVertDeg = dAngVertDeg ;
|
|
if ( pdAngOrizzDeg != nullptr)
|
|
*pdAngOrizzDeg = dAngOrizzDeg ;
|
|
if ( pdDist != nullptr)
|
|
*pdDist = m_dDistCamera ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
Scene::GetCameraDir( void)
|
|
{
|
|
if ( m_vtDirCamera.IsZplus())
|
|
return CT_TOP ;
|
|
else if ( m_vtDirCamera.IsYminus())
|
|
return CT_FRONT ;
|
|
else if ( m_vtDirCamera.IsXplus())
|
|
return CT_RIGHT ;
|
|
else if ( m_vtDirCamera.IsYplus())
|
|
return CT_BACK ;
|
|
else if ( m_vtDirCamera.IsXminus())
|
|
return CT_LEFT ;
|
|
else if ( m_vtDirCamera.IsZminus())
|
|
return CT_BOTTOM ;
|
|
else if ( AreSameVectorNear( m_vtDirCamera, Vector3d( - SQRT1_3, - SQRT1_3, SQRT1_3)))
|
|
return CT_ISO_SW ;
|
|
else if ( AreSameVectorNear( m_vtDirCamera, Vector3d( SQRT1_3, - SQRT1_3, SQRT1_3)))
|
|
return CT_ISO_SE ;
|
|
else if ( AreSameVectorNear( m_vtDirCamera, Vector3d( SQRT1_3, SQRT1_3, SQRT1_3)))
|
|
return CT_ISO_NE ;
|
|
else if ( AreSameVectorNear( m_vtDirCamera, Vector3d( - SQRT1_3, SQRT1_3, SQRT1_3)))
|
|
return CT_ISO_NW ;
|
|
else
|
|
return CT_NONE ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
Point3d
|
|
Scene::GetProjectedCenter( void)
|
|
{
|
|
Point3d ptVCen ;
|
|
if ( ! Project( m_ptCenter, ptVCen))
|
|
ptVCen.Set( 0, 0, 0) ;
|
|
|
|
return ptVCen ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Scene::CalcDirUp( void)
|
|
{
|
|
// verifico se il calcolo è necessario
|
|
if ( m_bUpOk)
|
|
return true ;
|
|
// direzione perpendicolare giacente nel piano XY
|
|
// ( m_vtDirCamera è opposta alla direzione in cui si guarda)
|
|
Vector3d vtPerpXY = m_vtDirCamera ^ Z_AX ;
|
|
if ( ! vtPerpXY.Normalize()) {
|
|
if ( m_vtDirCamera.z < 0)
|
|
vtPerpXY = X_AX ;
|
|
else
|
|
vtPerpXY = - X_AX ;
|
|
}
|
|
// direzione Up
|
|
m_vtUp = vtPerpXY ^ m_vtDirCamera ;
|
|
m_bUpOk = m_vtUp.Normalize() ;
|
|
// invalido ExtView
|
|
m_bExtViewOk = false ;
|
|
return m_bUpOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Scene::CalcCameraFrame( Frame3d& frView)
|
|
{
|
|
// verifico direzione camera Up
|
|
if ( ! CalcDirUp())
|
|
return false ;
|
|
// eseguo il calcolo
|
|
Vector3d vtZ = m_vtDirCamera ;
|
|
Vector3d vtY = m_vtUp ;
|
|
Vector3d vtX = vtY ^ vtZ ;
|
|
if ( ! frView.Set( m_ptCenter + m_dDistCamera * vtZ, vtX, vtY, vtZ))
|
|
return false ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Scene::PanCamera( const Point3d& ptWinOld, const Point3d& ptWinNew)
|
|
{
|
|
// porto i due punti in coordinate mondo
|
|
double dZCenter = GetProjectedCenter().z ;
|
|
Point3d ptViewOld( ptWinOld.x, ptWinOld.y, dZCenter) ;
|
|
Point3d ptWorldOld ;
|
|
if ( ! UnProject( ptViewOld, ptWorldOld))
|
|
return false ;
|
|
Point3d ptViewNew( ptWinNew.x, ptWinNew.y, dZCenter) ;
|
|
Point3d ptWorldNew ;
|
|
if ( ! UnProject( ptViewNew, ptWorldNew))
|
|
return false ;
|
|
// calcolo lo spostamento tra i due punti
|
|
Vector3d vtMove = ptWorldNew - ptWorldOld ;
|
|
// applico questo spostamento al centro di vista
|
|
return SetCenter( GetCenter() - vtMove) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Scene::RotateCamera( const Point3d& ptWinOld, const Point3d& ptWinNew)
|
|
{
|
|
const double MIN_ANG_VERT = 0.1 ;
|
|
const double MAX_ANG_VERT = 179.9 ;
|
|
|
|
// angoli correnti della camera
|
|
double dAngVertDeg ;
|
|
double dAngOrizzDeg ;
|
|
GetCamera( &dAngVertDeg, &dAngOrizzDeg) ;
|
|
|
|
// incrementi
|
|
double dDeltaAngVertDeg = ( ptWinNew.y - ptWinOld.y) / m_nViewportH * 360 ;
|
|
double dDeltaAngOrizzDeg = ( ptWinNew.x - ptWinOld.x) / m_nViewportW * 360 ;
|
|
|
|
// calcolo nuovi angoli e limitazione dell'angolo verticale
|
|
dAngVertDeg -= dDeltaAngVertDeg ;
|
|
if ( dAngVertDeg < MIN_ANG_VERT)
|
|
dAngVertDeg = MIN_ANG_VERT ;
|
|
else if ( dAngVertDeg > MAX_ANG_VERT)
|
|
dAngVertDeg = MAX_ANG_VERT ;
|
|
dAngOrizzDeg -= dDeltaAngOrizzDeg ;
|
|
|
|
// imposto nuova direzione camera
|
|
return SetCamera( dAngVertDeg, dAngOrizzDeg, 0) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Scene::ZoomAll( void)
|
|
{
|
|
// aggiorno l'ingombro
|
|
UpdateExtension() ;
|
|
|
|
// traslo il centro di vista nel centro del box
|
|
Point3d ptExtCent ;
|
|
if ( ! m_b3ExtWorld.GetCenter( ptExtCent))
|
|
return false ;
|
|
m_ptCenter = ptExtCent ;
|
|
m_bExtViewOk = false ;
|
|
|
|
// calcolo nuovi dati di ingombro
|
|
CalcDimViewFromExtView() ;
|
|
CalcClippingPlanesFromExtView() ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Scene::ZoomChange( double dCoeff)
|
|
{
|
|
const double MIN_COEFF = 0.5 ;
|
|
const double MAX_COEFF = 2 ;
|
|
|
|
// controllo i limiti
|
|
if ( dCoeff < MIN_COEFF)
|
|
dCoeff = MIN_COEFF ;
|
|
else if ( dCoeff > MAX_COEFF)
|
|
dCoeff = MAX_COEFF ;
|
|
// cambio le dimensioni di zoom
|
|
m_dHalfWidth *= dCoeff ;
|
|
m_dHalfHeight *= dCoeff ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Scene::ZoomOnPoint( const Point3d& ptWin, double dCoeff)
|
|
{
|
|
// porto il punto in coordinate mondo
|
|
Point3d ptView( ptWin.x, ptWin.y, GetProjectedCenter().z) ;
|
|
Point3d ptWorld ;
|
|
if ( ! UnProject( ptView, ptWorld))
|
|
return false ;
|
|
// modifico opportunamente il centro di vista
|
|
Point3d ptNewCen = ptWorld + ( GetCenter() - ptWorld) * dCoeff ;
|
|
SetCenter( ptNewCen) ;
|
|
// eseguo lo zoom
|
|
return ZoomChange( dCoeff) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Scene::ZoomWin( const Point3d& ptWin1, const Point3d& ptWin2)
|
|
{
|
|
// porto i punti in coordinate mondo
|
|
Point3d ptWorld1 ;
|
|
if ( ! UnProject( Point3d( ptWin1.x, ptWin1.y, GetProjectedCenter().z), ptWorld1))
|
|
return false ;
|
|
Point3d ptWorld2 ;
|
|
if ( ! UnProject( Point3d( ptWin2.x, ptWin2.y, GetProjectedCenter().z), ptWorld2))
|
|
return false ;
|
|
|
|
// recupero il riferimento della camera (vista)
|
|
Frame3d frView ;
|
|
if ( ! CalcCameraFrame( frView))
|
|
return false ;
|
|
|
|
// porto i punti in coordinate camera (vista)
|
|
Point3d ptView1 = ptWorld1 ;
|
|
ptView1.ToLoc( frView) ;
|
|
Point3d ptView2 = ptWorld2 ;
|
|
ptView2.ToLoc( frView) ;
|
|
|
|
// imposto il nuovo centro di vista
|
|
Point3d ptNewCen = 0.5 * ( ptWorld1 + ptWorld2) ;
|
|
SetCenter( ptNewCen) ;
|
|
|
|
// imposto il nuovo zoom
|
|
double dHalfWidth = 0.5 * fabs( ptView1.x - ptView2.x) ;
|
|
double dHalfHeight = 0.5 * fabs( ptView1.y - ptView2.y) ;
|
|
|
|
// adatto le dimensioni a quelle della vista
|
|
return AdjustDimView( dHalfWidth, dHalfHeight) ;
|
|
} |