Files
EgtGraphics/SceneCamera.cpp
T
Dario Sassi 3e0e4e55a2 EgtGraphics 1.5b2 :
- aggiunta gestione ObjNewGraphics e ObjOldGraphics.
2014-02-15 15:46:56 +00:00

299 lines
8.6 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) ;
if ( dDist < EPS_SMALL)
m_dDistCamera = STD_DIST_CAMERA ;
else
m_dDistCamera = __max( dDist, MIN_DIST_CAMERA) ;
// invalido Up e ExtView
m_bUpOk = false ;
m_bExtViewOk = false ;
// calcolo nuovi dati di Z clipping
CalcClippingPlanesFromExtView() ;
return true ;
}
//----------------------------------------------------------------------------
bool
Scene::SetCamera( int nDir, double dDist)
{
const double ANG_VERT_ISOVIEW = 54.73561032 ;
double dAngVertDeg ;
double dAngOrizzDeg ;
switch ( nDir) {
case CT_TOP :
dAngVertDeg = 0 ;
dAngOrizzDeg = 0 ;
break ;
case CT_FRONT :
dAngVertDeg = 90 ;
dAngOrizzDeg = -90 ;
break ;
case CT_RIGHT :
dAngVertDeg = 90 ;
dAngOrizzDeg = 0 ;
break ;
case CT_BACK :
dAngVertDeg = 90 ;
dAngOrizzDeg = 90 ;
break ;
case CT_LEFT :
dAngVertDeg = 90 ;
dAngOrizzDeg = 180 ;
break ;
case CT_BOTTOM :
dAngVertDeg = 180 ;
dAngOrizzDeg = 0 ;
break ;
case CT_ISO_SW :
dAngVertDeg = ANG_VERT_ISOVIEW ;
dAngOrizzDeg = -135 ;
break ;
case CT_ISO_SE :
dAngVertDeg = ANG_VERT_ISOVIEW ;
dAngOrizzDeg = -45 ;
break ;
case CT_ISO_NE :
dAngVertDeg = ANG_VERT_ISOVIEW ;
dAngOrizzDeg = 45 ;
break ;
case CT_ISO_NW :
dAngVertDeg = ANG_VERT_ISOVIEW ;
dAngOrizzDeg = 135 ;
break ;
default :
return false ;
break ;
}
return SetCamera( dAngVertDeg, dAngOrizzDeg, dDist) ;
}
//----------------------------------------------------------------------------
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::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) ;
}