983 lines
30 KiB
C++
983 lines
30 KiB
C++
//----------------------------------------------------------------------------
|
|
// EgalTech 2013-2014
|
|
//----------------------------------------------------------------------------
|
|
// File : Scene.cpp Data : 03.02.14 Versione : 1.5b1
|
|
// Contenuto : Implementazione della classe gestione scena.
|
|
//
|
|
//
|
|
//
|
|
// Modifiche : 29.01.14 DS Creazione modulo.
|
|
//
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
//--------------------------- Include ----------------------------------------
|
|
#include "stdafx.h"
|
|
#include "EGrScene.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 ;
|
|
static const double MIN_EXTENSION = 50 ;
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
EGrScene::EGrScene( void)
|
|
{
|
|
m_pLogger = nullptr ;
|
|
// Context data
|
|
m_hDC = nullptr ;
|
|
m_hRC = nullptr ;
|
|
memset( &m_wglewc, 0, sizeof( WGLEWContext)) ;
|
|
memset( &m_glewc, 0, sizeof( GLEWContext)) ;
|
|
m_bNewWay = false ;
|
|
// Geom data
|
|
SetExtension( BBox3d( -MIN_EXTENSION, -MIN_EXTENSION, -MIN_EXTENSION,
|
|
MIN_EXTENSION, MIN_EXTENSION, MIN_EXTENSION)) ;
|
|
// Viewport
|
|
m_nViewportW = 0 ;
|
|
m_nViewportH = 0 ;
|
|
// View data
|
|
m_ptCenter = ORIG ;
|
|
SetCamera( 0, 0, 0) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
EGrScene::~EGrScene( void)
|
|
{
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
EGrScene::Init( ILogger* pLogger)
|
|
{
|
|
m_pLogger = pLogger ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
EGrScene::CreateContext( HDC hDC, int nDriver, bool b2Buff, int nColorBits, int nDepthBits)
|
|
{
|
|
// verifico validità Device Context
|
|
if ( hDC == nullptr)
|
|
return false ;
|
|
m_hDC = hDC ;
|
|
|
|
// riporto nei limiti il tipo di driver
|
|
if ( nDriver < OD_SOFT)
|
|
nDriver = OD_SOFT ;
|
|
else if ( nDriver > OD_NEW)
|
|
nDriver = OD_NEW ;
|
|
|
|
// assegno formato pixel
|
|
PIXELFORMATDESCRIPTOR pfd ;
|
|
memset( &pfd, 0, sizeof(PIXELFORMATDESCRIPTOR)) ;
|
|
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR) ;
|
|
pfd.nVersion = 1 ;
|
|
pfd.dwFlags = ( b2Buff ? PFD_DOUBLEBUFFER : 0) | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW ;
|
|
pfd.iPixelType = PFD_TYPE_RGBA ;
|
|
pfd.cColorBits = nColorBits ;
|
|
pfd.cDepthBits = nDepthBits ;
|
|
pfd.iLayerType = PFD_MAIN_PLANE ;
|
|
|
|
int nPixelFormat = ChoosePixelFormat( m_hDC, &pfd) ;
|
|
if ( nPixelFormat == 0)
|
|
return false ;
|
|
if ( nDriver == OD_SOFT) {
|
|
int nPixFormGen = ChooseGenPixelFormat( nPixelFormat, b2Buff, nColorBits, nDepthBits) ;
|
|
if ( nPixFormGen != 0)
|
|
nPixelFormat = nPixFormGen ;
|
|
}
|
|
if ( ! SetPixelFormat( m_hDC, nPixelFormat, &pfd))
|
|
return false ;
|
|
|
|
HGLRC tempContext = wglCreateContext( m_hDC) ;
|
|
wglMakeCurrent( m_hDC, tempContext) ;
|
|
|
|
GLenum WglewInitResult ;
|
|
WglewInitResult = wglewInit() ;
|
|
|
|
if ( WglewInitResult != GLEW_OK)
|
|
LOG_INFO( m_pLogger, "WGLEW is not initialized !")
|
|
|
|
int attribs[10] ;
|
|
if ( nDriver == OD_SOFT) {
|
|
attribs[0] = WGL_CONTEXT_MAJOR_VERSION_ARB ;
|
|
attribs[1] = 1 ;
|
|
attribs[2] = WGL_CONTEXT_MINOR_VERSION_ARB ;
|
|
attribs[3] = 1 ;
|
|
attribs[4] = 0 ;
|
|
}
|
|
else if ( nDriver == OD_OLD) {
|
|
attribs[0] = WGL_CONTEXT_MAJOR_VERSION_ARB ;
|
|
attribs[1] = 2 ;
|
|
attribs[2] = WGL_CONTEXT_MINOR_VERSION_ARB ;
|
|
attribs[3] = 0 ;
|
|
attribs[4] = 0 ;
|
|
}
|
|
else {
|
|
attribs[0] = WGL_CONTEXT_MAJOR_VERSION_ARB ;
|
|
attribs[1] = 3 ;
|
|
attribs[2] = WGL_CONTEXT_MINOR_VERSION_ARB ;
|
|
attribs[3] = 0 ;
|
|
attribs[4] = WGL_CONTEXT_PROFILE_MASK_ARB ;
|
|
attribs[5] = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB ;
|
|
attribs[6] = 0 ;
|
|
}
|
|
|
|
if ( wglewIsSupported( "WGL_ARB_create_context") == 1) {
|
|
m_hRC = wglCreateContextAttribsARB( m_hDC, 0, attribs) ;
|
|
wglMakeCurrent( m_hDC, NULL) ;
|
|
wglDeleteContext( tempContext) ;
|
|
wglMakeCurrent( m_hDC, m_hRC) ;
|
|
}
|
|
else {
|
|
//It's not possible to make a GL 3.x context. Use the old style context (GL 2.1 and before)
|
|
m_hRC = tempContext ;
|
|
LOG_INFO( m_pLogger, "WGL_ARB_create_context missing !")
|
|
}
|
|
|
|
// verifico validità Rendering Context
|
|
if ( m_hRC == nullptr)
|
|
return false ;
|
|
|
|
GLenum GlewInitResult ;
|
|
glewExperimental = GL_TRUE ;
|
|
GlewInitResult = glewInit() ;
|
|
|
|
if ( GlewInitResult != GLEW_OK)
|
|
LOG_INFO( m_pLogger, "GLEW is not initialized !")
|
|
|
|
// verifico se posso lavorare in modalità nuova
|
|
m_bNewWay = ( nDriver == OD_NEW && glewIsSupported( "GL_VERSION_3_0") == 1) ;
|
|
if ( ! m_bNewWay)
|
|
LOG_INFO( m_pLogger, "OpenGL old way rendering !")
|
|
|
|
// reset stato di errore di OpenGL
|
|
glGetError() ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
EGrScene::ChooseGenPixelFormat( int nPfd, bool b2Buff, int nColorBits, int nDepthBits)
|
|
{
|
|
PIXELFORMATDESCRIPTOR pfdR ;
|
|
|
|
|
|
// verifica del pixel format proposto
|
|
int nTotPfd = DescribePixelFormat( m_hDC, nPfd, sizeof(PIXELFORMATDESCRIPTOR), &pfdR) ;
|
|
if ( pfdR.dwFlags & PFD_GENERIC_FORMAT &&
|
|
! ( pfdR.dwFlags & PFD_GENERIC_ACCELERATED))
|
|
return nPfd ;
|
|
|
|
// eventuale ricerca di un pixel format soddisfacente
|
|
int nIOpt = 0 ;
|
|
int nErrOpt = 1000 ;
|
|
for ( int nI = 1 ; nI <= nTotPfd ; nI ++) {
|
|
DescribePixelFormat( m_hDC, nI, sizeof(PIXELFORMATDESCRIPTOR), &pfdR) ;
|
|
if ( pfdR.dwFlags & PFD_GENERIC_FORMAT &&
|
|
! (pfdR.dwFlags & PFD_GENERIC_ACCELERATED) &&
|
|
( ! b2Buff || pfdR.dwFlags & PFD_DOUBLEBUFFER)) {
|
|
int nErr = abs( nColorBits - pfdR.cColorBits) +
|
|
abs( nDepthBits - pfdR.cDepthBits) ;
|
|
if ( nErr < nErrOpt) {
|
|
nErrOpt = nErr ;
|
|
nIOpt = nI ;
|
|
}
|
|
}
|
|
}
|
|
|
|
return nIOpt ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
EGrScene::MakeCurrent( void)
|
|
{
|
|
// se RC della scena non è definito, errore
|
|
if ( m_hRC == nullptr)
|
|
return false ;
|
|
|
|
// se RC della scena non è quello corrente, lo imposto
|
|
HGLRC hRC = wglGetCurrentContext() ;
|
|
if ( m_hRC != hRC)
|
|
return ( wglMakeCurrent( m_hDC, m_hRC) != 0) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
string
|
|
EGrScene::GetOpenGLInfo( void)
|
|
{
|
|
string sInfo = "OpenGL " ;
|
|
|
|
if ( MakeCurrent()) {
|
|
const char* p ;
|
|
if ( ( p = reinterpret_cast<const char*> ( glGetString( GL_VERSION))) != nullptr)
|
|
sInfo += p ;
|
|
sInfo += " " ;
|
|
if ( ( p = reinterpret_cast<const char*> ( glGetString( GL_VENDOR))) != nullptr)
|
|
sInfo += p ;
|
|
sInfo += " " ;
|
|
if ( ( p = reinterpret_cast<const char*> ( glGetString( GL_RENDERER))) != nullptr)
|
|
sInfo += p ;
|
|
}
|
|
else
|
|
sInfo += "ERROR" ;
|
|
|
|
// reset stato di errore di OpenGL
|
|
glGetError() ;
|
|
|
|
return sInfo ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
string
|
|
EGrScene::GetGLSLInfo( void)
|
|
{
|
|
string sInfo = "GLSL " ;
|
|
|
|
if ( MakeCurrent()) {
|
|
const char* p ;
|
|
if ( ( p = reinterpret_cast<const char*> ( glGetString( GL_SHADING_LANGUAGE_VERSION))) != nullptr)
|
|
sInfo += p ;
|
|
else
|
|
sInfo += "NONE" ;
|
|
}
|
|
else
|
|
sInfo += "ERROR" ;
|
|
|
|
// reset stato di errore di OpenGL
|
|
glGetError() ;
|
|
|
|
return sInfo ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
string
|
|
EGrScene::GetPixelFormatInfo( void)
|
|
{
|
|
string sInfo = "PixFmt " ;
|
|
|
|
if ( MakeCurrent()) {
|
|
int nPixFmt ;
|
|
PIXELFORMATDESCRIPTOR Pfd ;
|
|
if ( ( nPixFmt = GetPixelFormat( m_hDC)) > 0 &&
|
|
DescribePixelFormat( m_hDC, nPixFmt, sizeof(PIXELFORMATDESCRIPTOR), &Pfd) > 0) {
|
|
// indice
|
|
sInfo += ToString( nPixFmt) ;
|
|
// tipo di driver
|
|
if ( ! ( Pfd.dwFlags & PFD_GENERIC_FORMAT))
|
|
sInfo += " ICD" ;
|
|
else if ( Pfd.dwFlags & PFD_GENERIC_ACCELERATED)
|
|
sInfo += " MCD" ;
|
|
else
|
|
sInfo += " GEN" ;
|
|
// singolo o doppio buffer
|
|
sInfo += ( ( Pfd.dwFlags & PFD_DOUBLEBUFFER) ? " BUFF2" : " BUFF1") ;
|
|
// RGBA o COLORINDEX
|
|
sInfo += ( ( Pfd.iPixelType == PFD_TYPE_RGBA) ? " RGBA" : " CI") ;
|
|
// color bits
|
|
sInfo += ToString( Pfd.cColorBits) ;
|
|
// depth bits
|
|
sInfo += " Z" + ToString( Pfd.cDepthBits) ;
|
|
}
|
|
else
|
|
sInfo = "NO DESCRIBE" ;
|
|
}
|
|
else
|
|
sInfo += "ERROR" ;
|
|
|
|
// reset stato di errore di OpenGL
|
|
glGetError() ;
|
|
|
|
return sInfo ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
EGrScene::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
|
|
EGrScene::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
|
|
EGrScene::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
|
|
EGrScene::GetCamera( double* pdAngVertDeg, double* pdAngOrizzDeg, double* pdDist)
|
|
{
|
|
m_vtDirCamera.ToSpherical( nullptr, pdAngVertDeg, pdAngOrizzDeg) ;
|
|
if ( pdDist != nullptr)
|
|
*pdDist = m_dDistCamera ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
EGrScene::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 ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
EGrScene::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
|
|
EGrScene::SetExtension( const BBox3d& b3Ext)
|
|
{
|
|
if ( b3Ext.IsEmpty())
|
|
return false ;
|
|
|
|
m_b3ExtWorld = b3Ext ;
|
|
m_bExtViewOk = false ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
EGrScene::CalcExtView( void)
|
|
{
|
|
// verifico se il calcolo è necessario
|
|
if ( m_bExtViewOk && m_bUpOk)
|
|
return true ;
|
|
// calcolo direzione camera Up
|
|
if ( ! CalcDirUp())
|
|
return false ;
|
|
// calcolo il riferimento di vista
|
|
Frame3d frView ;
|
|
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 ;
|
|
// calcolo l'estensione nel riferimento di vista
|
|
m_b3ExtView = m_b3ExtWorld ;
|
|
m_b3ExtView.ToLoc( frView) ;
|
|
m_bExtViewOk = true ;
|
|
return m_bExtViewOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
EGrScene::ZoomAll( void)
|
|
{
|
|
// 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
|
|
EGrScene::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
|
|
EGrScene::CalcDimViewFromExtView( void)
|
|
{
|
|
// calcolo estensione nel riferimento di vista
|
|
if ( ! CalcExtView())
|
|
return false ;
|
|
|
|
// recupero gli ingombri
|
|
Point3d ptMin ;
|
|
Point3d ptMax ;
|
|
if ( ! m_b3ExtView.GetMinMax( ptMin, ptMax))
|
|
return false ;
|
|
|
|
// ricavo le dimensioni
|
|
const double COEFF = 1.05 ;
|
|
double dHalfWidth = COEFF * max( fabs( ptMin.x), fabs( ptMax.x)) ;
|
|
double dHalfHeight = COEFF * max( fabs( ptMin.y), fabs( ptMax.y)) ;
|
|
|
|
// adatto le dimensioni a quelle della vista
|
|
return AdjustDimView( dHalfWidth, dHalfHeight) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
EGrScene::AdjustDimView( double dHalfWidth, double dHalfHeight)
|
|
{
|
|
// se non assegnate, recupero dimensioni vista
|
|
if ( m_nViewportW == 0) {
|
|
HWND hWnd = ::WindowFromDC( m_hDC) ;
|
|
RECT rect ;
|
|
if ( ! ::GetClientRect( hWnd, &rect))
|
|
return false ;
|
|
m_nViewportW = rect.right ;
|
|
m_nViewportH = rect.bottom ;
|
|
// aggiorno la vista
|
|
glViewport( 0, 0, m_nViewportW, m_nViewportH) ;
|
|
// verifico presenza errori
|
|
GLenum nErr = glGetError() ;
|
|
if ( nErr != GL_NO_ERROR) {
|
|
string sOut = "First glViewport OpenGL error " + ToString( (int)nErr) ;
|
|
LOG_INFO( m_pLogger, sOut.c_str())
|
|
}
|
|
}
|
|
|
|
// adatto il rapporto tra le dimensioni calcolate a quello delle dimensioni della vista
|
|
double dAspect = m_nViewportH / ( double) m_nViewportW ;
|
|
if ( dAspect * dHalfWidth > dHalfHeight) {
|
|
m_dHalfWidth = dHalfWidth ;
|
|
m_dHalfHeight = dAspect * dHalfWidth ;
|
|
}
|
|
else {
|
|
m_dHalfWidth = dHalfHeight / dAspect ;
|
|
m_dHalfHeight = dHalfHeight ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
EGrScene::CalcClippingPlanesFromExtView( void)
|
|
{
|
|
// calcolo estensione nel riferimento di vista
|
|
if ( ! CalcExtView())
|
|
return false ;
|
|
|
|
// recupero gli ingombri
|
|
Point3d ptCenter ;
|
|
Vector3d vtExtent ;
|
|
if ( ! m_b3ExtView.GetCenterExtent( ptCenter, vtExtent))
|
|
return false ;
|
|
// ricavo la posizione dei piani di clipping sull'asse Z di vista
|
|
const double EXP_COEFF = 1.05 ;
|
|
double dExtent = __max( ( EXP_COEFF * vtExtent.z), MIN_EXTENSION) ;
|
|
m_dZNear = - ( ptCenter.z + dExtent) ;
|
|
m_dZFar = - ( ptCenter.z - dExtent) ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
EGrScene::Reshape( int nW, int nH)
|
|
{
|
|
if ( ! MakeCurrent())
|
|
return true ;
|
|
|
|
// assegno le dimensioni della vista
|
|
m_nViewportW = nW ;
|
|
m_nViewportH = nH ;
|
|
|
|
// aggiorno la vista
|
|
glViewport( 0, 0, m_nViewportW, m_nViewportH) ;
|
|
|
|
// verifico presenza errori
|
|
GLenum nErr = glGetError() ;
|
|
if ( nErr != GL_NO_ERROR) {
|
|
string sOut = "Reshape OpenGL error " + ToString( (int)nErr) ;
|
|
LOG_INFO( m_pLogger, sOut.c_str())
|
|
}
|
|
|
|
// aggiorno
|
|
AdjustDimView( m_dHalfWidth, m_dHalfHeight) ;
|
|
|
|
// ridisegno
|
|
return Draw() ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
EGrScene::Prepare( void)
|
|
{
|
|
// imposto il rendering corrente
|
|
if ( ! MakeCurrent())
|
|
return false ;
|
|
|
|
// imposto il colore dello sfondo
|
|
glClearColor( 0.1f, 0.1f, 0.5f, 0.0f) ;
|
|
|
|
// eventuale ricalcolo parametri di vista
|
|
CalcDirUp() ;
|
|
|
|
// imposto matrice di proiezione
|
|
glMatrixMode( GL_PROJECTION) ;
|
|
glLoadIdentity() ;
|
|
glOrtho( - m_dHalfWidth, m_dHalfWidth, - m_dHalfHeight, m_dHalfHeight, m_dZNear, m_dZFar) ;
|
|
|
|
// imposto matrice modello/vista
|
|
glMatrixMode( GL_MODELVIEW) ;
|
|
glLoadIdentity() ;
|
|
Point3d ptCamera = m_ptCenter + m_dDistCamera * m_vtDirCamera ;
|
|
gluLookAt( ptCamera.x, ptCamera.y, ptCamera.z,
|
|
m_ptCenter.x, m_ptCenter.y, m_ptCenter.z,
|
|
m_vtUp.x, m_vtUp.y, m_vtUp.z) ;
|
|
|
|
// verifico presenza errori
|
|
GLenum nErr = glGetError() ;
|
|
if ( nErr != GL_NO_ERROR) {
|
|
string sOut = "Prepare OpenGL error " + ToString( (int)nErr) ;
|
|
LOG_INFO( m_pLogger, sOut.c_str())
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
EGrScene::Draw( void)
|
|
{
|
|
// imposto
|
|
if ( ! Prepare())
|
|
return false ;
|
|
|
|
// cancello
|
|
glClear( GL_COLOR_BUFFER_BIT) ;
|
|
|
|
// disegno
|
|
if ( m_bNewWay) {
|
|
for ( int i = 0 ; i < NUM_VAO ; ++ i) {
|
|
if ( m_vaoID[i] != 0) {
|
|
glBindVertexArray( m_vaoID[i]) ;
|
|
glDrawArrays( m_nMode[i], 0, m_nCount[i]) ;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
for ( int i = 0 ; i < NUM_VAO ; ++ i) {
|
|
if ( m_nCount[i] != 0) {
|
|
glBegin( m_nMode[i]) ;
|
|
for ( int j = 0 ; j < m_nCount[i] ; ++ j)
|
|
glVertex3f( m_v3fVect[i][j].x, m_v3fVect[i][j].y, m_v3fVect[i][j].z) ;
|
|
glEnd() ;
|
|
}
|
|
}
|
|
}
|
|
|
|
// aggiorno
|
|
glFlush() ;
|
|
|
|
// verifico presenza errori
|
|
GLenum nErr = glGetError() ;
|
|
if ( nErr != GL_NO_ERROR) {
|
|
string sOut = "Draw OpenGL error " + ToString( (int)nErr) ;
|
|
LOG_INFO( m_pLogger, sOut.c_str())
|
|
}
|
|
|
|
// scambio i buffer back e front ( eseguita solo se previsti)
|
|
if ( ! SwapBuffers( m_hDC))
|
|
LOG_INFO( m_pLogger, "Draw SwapBuffers error")
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void
|
|
EGrScene::Destroy( void)
|
|
{
|
|
wglMakeCurrent( nullptr, nullptr) ;
|
|
if ( m_hRC != nullptr) {
|
|
wglDeleteContext( m_hRC) ;
|
|
m_hRC = nullptr ;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void
|
|
EGrScene::SetData( int nType)
|
|
{
|
|
const int SQUARE = 1 ;
|
|
const int CUBE = 2 ;
|
|
const int TRIANGLE = 3 ;
|
|
|
|
switch ( nType) {
|
|
case SQUARE :
|
|
SetSquare() ;
|
|
break;
|
|
case CUBE :
|
|
SetCube() ;
|
|
break;
|
|
case TRIANGLE :
|
|
default :
|
|
SetTriangle() ;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void
|
|
EGrScene::SetSquare( void)
|
|
{
|
|
if ( ! MakeCurrent())
|
|
return ;
|
|
|
|
// vertici
|
|
Vert3f Point[4] ;
|
|
Point[0].Set( -0.5, -0.5, 0.0) ;
|
|
Point[1].Set( -0.5, 0.5, 0.0) ;
|
|
Point[2].Set( 0.5, 0.5, 0.0) ;
|
|
Point[3].Set( 0.5, -0.5, 0.0) ;
|
|
|
|
// dimensioni di ingombro
|
|
BBox3d b3Ext ;
|
|
for ( int i = 0 ; i < 4 ; ++ i)
|
|
b3Ext.Add( Point[i].x, Point[i].y, Point[i].z) ;
|
|
SetExtension( b3Ext) ;
|
|
|
|
if ( m_bNewWay) {
|
|
// inizializzo VAOs a non allocati
|
|
for ( int i = 0 ; i < NUM_VAO ; ++ i)
|
|
m_vaoID[i] = 0 ;
|
|
// VAO allocation
|
|
glGenVertexArrays( 1, &m_vaoID[0]) ;
|
|
if ( m_vaoID[0] == 0)
|
|
return ;
|
|
// First VAO setup
|
|
glBindVertexArray( m_vaoID[0]) ;
|
|
glGenBuffers( 1, &m_vboID[0]) ;
|
|
glBindBuffer( GL_ARRAY_BUFFER, m_vboID[0]) ;
|
|
m_nMode[0] = GL_LINE_STRIP ;
|
|
m_nCount[0] = 5 ;
|
|
glBufferData( GL_ARRAY_BUFFER, 5 * SIZEV3F, NULL, GL_STATIC_DRAW) ;
|
|
glBufferSubData( GL_ARRAY_BUFFER, 0 * SIZEV3F, SIZEV3F, &Point[0]) ;
|
|
glBufferSubData( GL_ARRAY_BUFFER, 1 * SIZEV3F, SIZEV3F, &Point[1]) ;
|
|
glBufferSubData( GL_ARRAY_BUFFER, 2 * SIZEV3F, SIZEV3F, &Point[2]) ;
|
|
glBufferSubData( GL_ARRAY_BUFFER, 3 * SIZEV3F, SIZEV3F, &Point[3]) ;
|
|
glBufferSubData( GL_ARRAY_BUFFER, 4 * SIZEV3F, SIZEV3F, &Point[0]) ;
|
|
glVertexAttribPointer( (GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0) ;
|
|
glEnableVertexAttribArray( 0) ;
|
|
glBindVertexArray( 0) ;
|
|
}
|
|
else {
|
|
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void
|
|
EGrScene::SetCube( void)
|
|
{
|
|
if ( ! MakeCurrent())
|
|
return ;
|
|
|
|
// vertici
|
|
Vert3f Point[8] ;
|
|
Point[0].Set( -0.5, -0.5, 0.0) ;
|
|
Point[1].Set( -0.5, 0.5, 0.0) ;
|
|
Point[2].Set( 0.5, 0.5, 0.0) ;
|
|
Point[3].Set( 0.5, -0.5, 0.0) ;
|
|
Point[4].Set( -0.5, -0.5, 1.0) ;
|
|
Point[5].Set( -0.5, 0.5, 1.0) ;
|
|
Point[6].Set( 0.5, 0.5, 1.0) ;
|
|
Point[7].Set( 0.5, -0.5, 1.0) ;
|
|
|
|
// dimensioni di ingombro
|
|
BBox3d b3Ext ;
|
|
for ( int i = 0 ; i < 8 ; ++ i)
|
|
b3Ext.Add( Point[i].x, Point[i].y, Point[i].z) ;
|
|
SetExtension( b3Ext) ;
|
|
|
|
if ( m_bNewWay) {
|
|
// inizializzo VAOs a non allocati
|
|
for ( int i = 0 ; i < NUM_VAO ; ++ i)
|
|
m_vaoID[i] = 0 ;
|
|
// VAO allocation
|
|
glGenVertexArrays( 3, &m_vaoID[0]) ;
|
|
if ( m_vaoID[0] == 0)
|
|
return ;
|
|
// First VAO setup
|
|
glBindVertexArray( m_vaoID[0]) ;
|
|
glGenBuffers( 1, &m_vboID[0]) ;
|
|
glBindBuffer( GL_ARRAY_BUFFER, m_vboID[0]) ;
|
|
m_nMode[0] = GL_LINE_STRIP ;
|
|
m_nCount[0] = 5 ;
|
|
glBufferData( GL_ARRAY_BUFFER, 5 * SIZEV3F, NULL, GL_STATIC_DRAW) ;
|
|
glBufferSubData( GL_ARRAY_BUFFER, 0 * SIZEV3F, SIZEV3F, &Point[0]) ;
|
|
glBufferSubData( GL_ARRAY_BUFFER, 1 * SIZEV3F, SIZEV3F, &Point[1]) ;
|
|
glBufferSubData( GL_ARRAY_BUFFER, 2 * SIZEV3F, SIZEV3F, &Point[2]) ;
|
|
glBufferSubData( GL_ARRAY_BUFFER, 3 * SIZEV3F, SIZEV3F, &Point[3]) ;
|
|
glBufferSubData( GL_ARRAY_BUFFER, 4 * SIZEV3F, SIZEV3F, &Point[0]) ;
|
|
glVertexAttribPointer( (GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0) ;
|
|
glEnableVertexAttribArray( 0) ;
|
|
glBindVertexArray( 0) ;
|
|
// Second VAO setup
|
|
glBindVertexArray( m_vaoID[1]) ;
|
|
glGenBuffers( 1, &m_vboID[1]) ;
|
|
glBindBuffer( GL_ARRAY_BUFFER, m_vboID[1]) ;
|
|
m_nMode[1] = GL_LINE_STRIP ;
|
|
m_nCount[1] = 5 ;
|
|
glBufferData( GL_ARRAY_BUFFER, 5 * SIZEV3F, NULL, GL_STATIC_DRAW) ;
|
|
glBufferSubData( GL_ARRAY_BUFFER, 0 * SIZEV3F, SIZEV3F, &Point[4]) ;
|
|
glBufferSubData( GL_ARRAY_BUFFER, 1 * SIZEV3F, SIZEV3F, &Point[5]) ;
|
|
glBufferSubData( GL_ARRAY_BUFFER, 2 * SIZEV3F, SIZEV3F, &Point[6]) ;
|
|
glBufferSubData( GL_ARRAY_BUFFER, 3 * SIZEV3F, SIZEV3F, &Point[7]) ;
|
|
glBufferSubData( GL_ARRAY_BUFFER, 4 * SIZEV3F, SIZEV3F, &Point[4]) ;
|
|
glVertexAttribPointer( (GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0) ;
|
|
glEnableVertexAttribArray( 0) ;
|
|
glBindVertexArray( 0) ;
|
|
// Third VAO setup
|
|
glBindVertexArray( m_vaoID[2]) ;
|
|
glGenBuffers( 1, &m_vboID[2]) ;
|
|
glBindBuffer( GL_ARRAY_BUFFER, m_vboID[2]) ;
|
|
m_nMode[2] = GL_LINES ;
|
|
m_nCount[2] = 8 ;
|
|
glBufferData( GL_ARRAY_BUFFER, 8 * SIZEV3F, NULL, GL_STATIC_DRAW) ;
|
|
glBufferSubData( GL_ARRAY_BUFFER, 0 * SIZEV3F, SIZEV3F, &Point[0]) ;
|
|
glBufferSubData( GL_ARRAY_BUFFER, 1 * SIZEV3F, SIZEV3F, &Point[4]) ;
|
|
glBufferSubData( GL_ARRAY_BUFFER, 2 * SIZEV3F, SIZEV3F, &Point[1]) ;
|
|
glBufferSubData( GL_ARRAY_BUFFER, 3 * SIZEV3F, SIZEV3F, &Point[5]) ;
|
|
glBufferSubData( GL_ARRAY_BUFFER, 4 * SIZEV3F, SIZEV3F, &Point[2]) ;
|
|
glBufferSubData( GL_ARRAY_BUFFER, 5 * SIZEV3F, SIZEV3F, &Point[6]) ;
|
|
glBufferSubData( GL_ARRAY_BUFFER, 6 * SIZEV3F, SIZEV3F, &Point[3]) ;
|
|
glBufferSubData( GL_ARRAY_BUFFER, 7 * SIZEV3F, SIZEV3F, &Point[7]) ;
|
|
glVertexAttribPointer( (GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0) ;
|
|
glEnableVertexAttribArray( 0) ;
|
|
glBindVertexArray( 0) ;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void
|
|
EGrScene::SetTriangle( void)
|
|
{
|
|
if ( ! MakeCurrent())
|
|
return ;
|
|
|
|
// vertici
|
|
Vert3f Point[6] ;
|
|
Point[0].Set( -0.3, 0.5, -1.0) ;
|
|
Point[1].Set( -0.8, -0.5, -1.0) ;
|
|
Point[2].Set( 0.2, -0.5, -1.0) ;
|
|
Point[3].Set( -0.2, 0.5, -1.0) ;
|
|
Point[4].Set( 0.3, -0.5, -1.0) ;
|
|
Point[5].Set( 0.8, 0.5, -1.0) ;
|
|
|
|
// dimensioni di ingombro
|
|
BBox3d b3Ext ;
|
|
for ( int i = 0 ; i < 6 ; ++ i)
|
|
b3Ext.Add( Point[i].x, Point[i].y, Point[i].z) ;
|
|
SetExtension( b3Ext) ;
|
|
|
|
if ( m_bNewWay) {
|
|
// inizializzo VAOs a non allocati
|
|
for ( int i = 0 ; i < NUM_VAO ; ++ i)
|
|
m_vaoID[i] = 0 ;
|
|
// VAOs allocation
|
|
glGenVertexArrays( 2, &m_vaoID[0]) ;
|
|
// First VAO setup
|
|
glBindVertexArray( m_vaoID[0]) ;
|
|
glGenBuffers( 1, &m_vboID[0]) ; //VBO allocation
|
|
glBindBuffer( GL_ARRAY_BUFFER, m_vboID[0]) ;
|
|
m_nMode[0] = GL_LINE_STRIP ;
|
|
m_nCount[0] = 4 ;
|
|
glBufferData( GL_ARRAY_BUFFER, 4 * SIZEV3F, NULL, GL_STATIC_DRAW) ;
|
|
glBufferSubData( GL_ARRAY_BUFFER, 0 * SIZEV3F, SIZEV3F, &Point[0]) ;
|
|
glBufferSubData( GL_ARRAY_BUFFER, 1 * SIZEV3F, SIZEV3F, &Point[1]) ;
|
|
glBufferSubData( GL_ARRAY_BUFFER, 2 * SIZEV3F, SIZEV3F, &Point[2]) ;
|
|
glBufferSubData( GL_ARRAY_BUFFER, 3 * SIZEV3F, SIZEV3F, &Point[0]) ;
|
|
glVertexAttribPointer( (GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0) ;
|
|
glEnableVertexAttribArray( 0) ;
|
|
glBindVertexArray( 0) ;
|
|
// Second VAO setup
|
|
glBindVertexArray( m_vaoID[1]) ;
|
|
glGenBuffers( 1, &m_vboID[1]) ; //VBO allocation
|
|
glBindBuffer( GL_ARRAY_BUFFER, m_vboID[1]) ;
|
|
m_nMode[1] = GL_LINE_STRIP ;
|
|
m_nCount[1] = 4 ;
|
|
glBufferData( GL_ARRAY_BUFFER, 4 * SIZEV3F, NULL, GL_STATIC_DRAW) ;
|
|
glBufferSubData( GL_ARRAY_BUFFER, 0 * SIZEV3F, SIZEV3F, &Point[3]) ;
|
|
glBufferSubData( GL_ARRAY_BUFFER, 1 * SIZEV3F, SIZEV3F, &Point[4]) ;
|
|
glBufferSubData( GL_ARRAY_BUFFER, 2 * SIZEV3F, SIZEV3F, &Point[5]) ;
|
|
glBufferSubData( GL_ARRAY_BUFFER, 3 * SIZEV3F, SIZEV3F, &Point[3]) ;
|
|
glVertexAttribPointer( (GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0) ;
|
|
glEnableVertexAttribArray( 0) ;
|
|
glBindVertexArray( 0) ;
|
|
}
|
|
else {
|
|
// First VAO setup
|
|
m_nMode[0] = GL_LINE_STRIP ;
|
|
m_nCount[0] = 4 ;
|
|
m_v3fVect[0].reserve( 4) ;
|
|
m_v3fVect[0].push_back( Point[0]) ;
|
|
m_v3fVect[0].push_back( Point[1]) ;
|
|
m_v3fVect[0].push_back( Point[2]) ;
|
|
m_v3fVect[0].push_back( Point[0]) ;
|
|
// Second VAO setup
|
|
m_nMode[1] = GL_LINE_STRIP ;
|
|
m_nCount[1] = 4 ;
|
|
m_v3fVect[1].reserve( 4) ;
|
|
m_v3fVect[1].push_back( Point[3]) ;
|
|
m_v3fVect[1].push_back( Point[4]) ;
|
|
m_v3fVect[1].push_back( Point[5]) ;
|
|
m_v3fVect[1].push_back( Point[3]) ;
|
|
// Third VAO null
|
|
m_nCount[2] = 0 ;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void
|
|
EGrScene::ResetData( void)
|
|
{
|
|
if ( m_bNewWay) {
|
|
if ( MakeCurrent()) {
|
|
glBindBuffer( GL_ARRAY_BUFFER, 0) ;
|
|
glDeleteBuffers( NUM_VAO, m_vboID) ;
|
|
glBindVertexArray( 0) ;
|
|
glDeleteVertexArrays( NUM_VAO, m_vaoID) ;
|
|
}
|
|
}
|
|
else {
|
|
for ( int i = 0 ; i < NUM_VAO ; ++ i)
|
|
m_v3fVect[i].clear() ;
|
|
}
|
|
}
|