EgtGraphics 2.7a2 :
- aggiunta vista prospettica con due modalità di zoom ( standard e dolly).
This commit is contained in:
+197
-24
@@ -24,6 +24,75 @@ using namespace std ;
|
||||
static const double MIN_DIST_CAMERA = 10 ;
|
||||
static const double STD_DIST_CAMERA = 1000 ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Scene::SetCameraType( bool bOrthoOrPersp)
|
||||
{
|
||||
m_bOrthographic = bOrthoOrPersp ;
|
||||
// ricalcolo i parametri di vista
|
||||
m_bDistOk = false ;
|
||||
CalcDistCamera() ;
|
||||
CalcClippingPlanesFromExtView() ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Scene::SetZoomType( int nZoomMode)
|
||||
{
|
||||
if ( nZoomMode != ZT_STD && nZoomMode != ZT_DOLLY)
|
||||
return false ;
|
||||
m_nPerspZoomType = nZoomMode ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
double
|
||||
Scene::CalcMinCameraDistance()
|
||||
{
|
||||
double dMinDist = MIN_DIST_CAMERA ;
|
||||
|
||||
// nel caso di vista prospettica la distanza della camera deve garantire di non finire dentro gli oggetti
|
||||
if ( ! m_bOrthographic) {
|
||||
|
||||
// calcolo il box di tutti gli oggetti visibili nel frame della camera
|
||||
Frame3d frCamera ;
|
||||
CalcCameraFrame( frCamera) ;
|
||||
BBox3d b3Tot ;
|
||||
if ( m_pGeomDB != nullptr)
|
||||
m_pGeomDB->GetGlobalBBox( GDB_ID_ROOT, b3Tot, BBF_ONLY_VISIBLE) ;
|
||||
b3Tot.ToLoc( frCamera) ;
|
||||
|
||||
// la distanza minima della camera è quella che garantisce di trovarsi ad una distanza pari almeno a PERSPECTIVE_NEAR_PLANE
|
||||
// dalla faccia del box davanti alla camera
|
||||
Point3d ptMax = b3Tot.GetMax() ;
|
||||
ptMax.ToGlob( frCamera) ;
|
||||
dMinDist = ( ptMax - m_ptCenter) * m_vtDirCamera + PERSPECTIVE_NEAR_PLANE + 10 * EPS_SMALL ;
|
||||
}
|
||||
|
||||
return dMinDist ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Scene::CalcDistCamera()
|
||||
{
|
||||
// verifico se il calcolo è necessario
|
||||
if ( m_bDistOk)
|
||||
return true ;
|
||||
|
||||
if ( m_dDistCamera < EPS_SMALL)
|
||||
m_dDistCamera = STD_DIST_CAMERA ;
|
||||
else {
|
||||
double dMinDist = CalcMinCameraDistance() ;
|
||||
if ( m_dDistCamera < dMinDist)
|
||||
m_dDistCamera = dMinDist ;
|
||||
}
|
||||
m_bDistOk = true ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Scene::SetCenter( const Point3d& ptCenter)
|
||||
@@ -41,9 +110,10 @@ Scene::SetCenter( const Point3d& ptCenter)
|
||||
bool
|
||||
Scene::SetCamera( double dAngVertDeg, double dAngOrizzDeg, double dDist)
|
||||
{
|
||||
// assegno la direzione e la distanza
|
||||
// assegno la direzione ed eventuale distanza
|
||||
m_vtDirCamera = FromSpherical( 1, dAngVertDeg, dAngOrizzDeg) ;
|
||||
m_dDistCamera = dDist ;
|
||||
if ( dDist > EPS_SMALL)
|
||||
m_dDistCamera = dDist ;
|
||||
if ( ! VerifyCamera())
|
||||
return false ;
|
||||
// se vista da sopra, impongo vtUp da angolo orizzontale
|
||||
@@ -103,7 +173,11 @@ Scene::SetCamera( int nDir, double dDist)
|
||||
}
|
||||
if ( nDir != CT_CPLANE)
|
||||
m_vtDirCamera.Rotate( Z_AX, m_nOrizzOffsCamera * ANG_RIGHT) ;
|
||||
m_dDistCamera = dDist ;
|
||||
|
||||
// assegno eventuale distanza
|
||||
if ( dDist > EPS_SMALL)
|
||||
m_dDistCamera = dDist ;
|
||||
|
||||
return VerifyCamera( nDir != CT_CPLANE) ;
|
||||
}
|
||||
|
||||
@@ -114,15 +188,16 @@ Scene::VerifyCamera( bool bUseOrizzOffsCamera)
|
||||
// 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) ;
|
||||
|
||||
// ricalcolo direzione Up
|
||||
m_bUpOk = false ;
|
||||
if ( ! CalcDirUp( bUseOrizzOffsCamera))
|
||||
return false ;
|
||||
|
||||
// verifico la distanza
|
||||
m_bDistOk = false ;
|
||||
CalcDistCamera() ;
|
||||
|
||||
// ricalcolo ExtView
|
||||
m_bExtViewOk = false ;
|
||||
if ( ! CalcExtView())
|
||||
@@ -203,11 +278,11 @@ Scene::GetProjectedCenter( void) const
|
||||
bool
|
||||
Scene::CalcDirUp( bool bUseOrizzOffsCamera)
|
||||
{
|
||||
// verifico se il calcolo è necessario
|
||||
// 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)
|
||||
// ( m_vtDirCamera è opposta alla direzione in cui si guarda)
|
||||
Vector3d vtPerpXY = m_vtDirCamera ^ Z_AX ;
|
||||
if ( ! vtPerpXY.Normalize()) {
|
||||
vtPerpXY = -X_AX ;
|
||||
@@ -256,7 +331,14 @@ Scene::PanCamera( const Point3d& ptWinOld, const Point3d& ptWinNew)
|
||||
// calcolo lo spostamento tra i due punti
|
||||
Vector3d vtMove = ptWorldNew - ptWorldOld ;
|
||||
// applico questo spostamento al centro di vista
|
||||
return SetCenter( GetCenter() - vtMove) ;
|
||||
SetCenter( GetCenter() - vtMove) ;
|
||||
// se dolly aggiusto la distanza per non entrare negli oggetti
|
||||
if ( ! m_bOrthographic && m_nPerspZoomType == ZT_DOLLY)
|
||||
CalcDistCamera() ;
|
||||
else
|
||||
m_bDistOk = true ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -302,6 +384,33 @@ Scene::ZoomAll( void)
|
||||
|
||||
// calcolo nuovi dati di ingombro
|
||||
CalcDimViewFromExtView() ;
|
||||
|
||||
if ( ! m_bOrthographic) {
|
||||
if ( m_nPerspZoomType == ZT_DOLLY) {
|
||||
// adatto la distanza della camera in modo che il fov resti al valore standard
|
||||
m_dDistCamera = m_dHalfHeight / tan( PERSPECTIVE_STD_FOV * 0.5 * DEGTORAD) + ( m_b3ExtView.GetMax().z - m_b3ExtView.GetMin().z) * 0.5 ;
|
||||
}
|
||||
else {
|
||||
// verifico di non finire dentro l'oggetto
|
||||
double dDiam ; m_b3ExtView.GetDiameter( dDiam) ;
|
||||
if ( m_dDistCamera < dDiam * 0.5)
|
||||
m_dDistCamera = dDiam * 0.5 ;
|
||||
|
||||
// il valore di m_dHalfHeight calcolato dal box non garantisce che l'oggetto sia interamente contenuto nel frustum
|
||||
// perchè è il valore in corrispondenza della faccia del box davanti alla camera. Per il calcolo del fov m_dHalfHeight
|
||||
// deve essere calcolato in corrispondenza di m_ptCenter
|
||||
// distanza della camera dalla faccia davanti del box
|
||||
double dDist = m_dDistCamera - ( m_b3ExtView.GetMax().z - m_b3ExtView.GetMin().z) * 0.5 ;
|
||||
// aggiorno le dimensioni
|
||||
double dAspect = m_dHalfWidth / m_dHalfHeight ;
|
||||
m_dHalfHeight = m_dHalfHeight / dDist * m_dDistCamera ;
|
||||
m_dHalfWidth = m_dHalfHeight * dAspect ;
|
||||
|
||||
}
|
||||
}
|
||||
// la distanza della camera è calcolata correttamente
|
||||
m_bDistOk = true ;
|
||||
|
||||
CalcClippingPlanesFromExtView() ;
|
||||
|
||||
return true ;
|
||||
@@ -344,8 +453,32 @@ Scene::ZoomObject( int nId)
|
||||
double dHalfHeight = COEFF * ( b3Obj.GetMax().y - b3Obj.GetMin().y) / 2 ;
|
||||
|
||||
// imposto il centro e le dimensioni di vista
|
||||
m_ptCenter = ptCent ;
|
||||
return AdjustDimView( dHalfWidth, dHalfHeight) ;
|
||||
m_ptCenter = ptCent ;
|
||||
if ( ! AdjustDimView( dHalfWidth, dHalfHeight))
|
||||
return false ;
|
||||
|
||||
if ( ! m_bOrthographic) {
|
||||
// cfr conti analoghi in ZoomAll
|
||||
if ( m_nPerspZoomType == ZT_DOLLY) {
|
||||
m_dDistCamera = m_dHalfHeight / tan( PERSPECTIVE_STD_FOV * 0.5 * DEGTORAD) + ( b3Obj.GetMax().z - b3Obj.GetMin().z) * 0.5 ;
|
||||
}
|
||||
else {
|
||||
// verifico di non finire dentro l'oggetto
|
||||
double dDiam ; b3Obj.GetDiameter( dDiam) ;
|
||||
if ( m_dDistCamera < dDiam * 0.5)
|
||||
m_dDistCamera = dDiam * 0.5 ;
|
||||
// distanza della camera dalla faccia davanti del box
|
||||
double dDist = m_dDistCamera - ( b3Obj.GetMax().z - b3Obj.GetMin().z) * 0.5 ;
|
||||
// ricalcolo le dimensioni
|
||||
double dAspect = m_dHalfWidth / m_dHalfHeight ;
|
||||
m_dHalfHeight = m_dHalfHeight / dDist * m_dDistCamera ;
|
||||
m_dHalfWidth = m_dHalfHeight * dAspect ;
|
||||
}
|
||||
}
|
||||
// la distanza della camera è calcolata per non finire dentro gli oggetti
|
||||
m_bDistOk = true ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -353,7 +486,19 @@ bool
|
||||
Scene::ZoomRadius( double dRadius)
|
||||
{
|
||||
// adatto le dimensioni a quelle della vista
|
||||
return AdjustDimView( dRadius, dRadius) ;
|
||||
if ( ! AdjustDimView( dRadius, dRadius))
|
||||
return false ;
|
||||
|
||||
// per il dolly va modificata la distanza dalla camera
|
||||
if ( ! m_bOrthographic && m_nPerspZoomType == ZT_DOLLY) {
|
||||
m_dDistCamera = m_dHalfHeight / tan( PERSPECTIVE_STD_FOV * 0.5 * DEGTORAD) ;
|
||||
// verifico la distanza della camera
|
||||
CalcDistCamera() ;
|
||||
}
|
||||
else
|
||||
m_bDistOk = true ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -363,14 +508,17 @@ 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 ;
|
||||
if ( ! m_bOrthographic && m_nPerspZoomType == ZT_DOLLY) {
|
||||
// per il dolly va modificata la distanza della camera
|
||||
m_dDistCamera *= dCoeff ;
|
||||
}
|
||||
else {
|
||||
// controllo i limiti
|
||||
dCoeff = clamp( dCoeff, MIN_COEFF, MAX_COEFF) ;
|
||||
m_dHalfWidth *= dCoeff ;
|
||||
m_dHalfHeight *= dCoeff ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -384,10 +532,24 @@ Scene::ZoomOnPoint( const Point3d& ptWin, double dCoeff)
|
||||
Point3d ptWorld ;
|
||||
if ( ! UnProject( ptView, ptWorld))
|
||||
return false ;
|
||||
|
||||
// modifico opportunamente il centro di vista
|
||||
Point3d ptNewCen = ptWorld + ( GetCenter() - ptWorld) * dCoeff ;
|
||||
Point3d ptOldCen = m_ptCenter ;
|
||||
Point3d ptNewCen = ptWorld + ( m_ptCenter - ptWorld) * dCoeff ;
|
||||
SetCenter( ptNewCen) ;
|
||||
// eseguo lo zoom
|
||||
|
||||
// nel caso di dolly verifico se il nuovo zoom fa entrare negli oggetti
|
||||
if ( ! m_bOrthographic && m_nPerspZoomType == ZT_DOLLY) {
|
||||
double dMinDist = CalcMinCameraDistance() ;
|
||||
if ( m_dDistCamera * dCoeff < dMinDist) {
|
||||
// adatto il coefficiente di zoom e ricalcolo il centro
|
||||
dCoeff = dMinDist / m_dDistCamera ;
|
||||
Point3d ptNewCenter = ptWorld + ( ptOldCen - ptWorld) * dCoeff ;
|
||||
SetCenter( ptNewCenter) ;
|
||||
}
|
||||
}
|
||||
m_bDistOk = true ;
|
||||
|
||||
return ZoomChange( dCoeff) ;
|
||||
}
|
||||
|
||||
@@ -421,7 +583,18 @@ Scene::ZoomWin( const Point3d& ptWin1, const Point3d& ptWin2)
|
||||
double dHalfHeight = 0.5 * abs( ptView1.y - ptView2.y) ;
|
||||
|
||||
// adatto le dimensioni a quelle della vista
|
||||
return AdjustDimView( dHalfWidth, dHalfHeight) ;
|
||||
if ( ! AdjustDimView( dHalfWidth, dHalfHeight))
|
||||
return false ;
|
||||
|
||||
// per il dolly va modificata la distanza della camera
|
||||
if ( ! m_bOrthographic && m_nPerspZoomType == ZT_DOLLY) {
|
||||
m_dDistCamera = m_dHalfHeight / tan( PERSPECTIVE_STD_FOV * 0.5 * DEGTORAD) ;
|
||||
CalcDistCamera() ;
|
||||
}
|
||||
else
|
||||
m_bDistOk = true ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user