EgtGraphics 2.7a2 :

- aggiunta vista prospettica con due modalità di zoom ( standard e dolly).
This commit is contained in:
SaraP
2025-01-23 10:07:48 +01:00
parent 0a28896ab6
commit d9c9622972
6 changed files with 334 additions and 99 deletions
+197 -24
View File
@@ -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 ;
}
//----------------------------------------------------------------------------