Files
EgtGraphics/SceneBasic.cpp
T
Dario Sassi ec813123d0 EgtGraphics 1.5c5 :
- nel disegno si tiene conto dello stato dell'oggetto (ON, SEL, OFF)
- gli oggetti selezionati vengono evidenziati.
2014-03-14 18:40:18 +00:00

720 lines
21 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 2013-2014
//----------------------------------------------------------------------------
// File : SceneBasic.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 "Scene.h"
#include "GraphObjs.h"
#include "DllMain.h"
#include "/EgtDev/Include/EgtILogger.h"
#include "/EgtDev/Include/EGnStringUtils.h"
#include "/EgtDev/Include/EGkFrame3d.h"
#include "/EgtDev/Include/EGkGdbConst.h"
#include "/EgtDev/Include/EGkGeomDB.h"
using namespace std ;
//--------------------------- Constants --------------------------------------
static const double MIN_EXTENSION = 50 ;
static const double MIN_ZCLIP_EXT = 5000 ;
//----------------------------------------------------------------------------
IEGrScene*
CreateEGrScene( void)
{
return static_cast<IEGrScene*> ( new(nothrow) Scene) ;
}
//----------------------------------------------------------------------------
Scene::Scene( void)
{
// Context data
m_hDC = nullptr ;
m_hRC = nullptr ;
memset( &m_wglewc, 0, sizeof( WGLEWContext)) ;
memset( &m_glewc, 0, sizeof( GLEWContext)) ;
m_bNewWay = false ;
// Camera e viewport
m_ptCenter = ORIG ;
SetCamera( 0, 0, 0) ;
m_nViewportW = 0 ;
m_nViewportH = 0 ;
// Sfondo
m_BackTop.Set( 128, 128, 128) ;
m_BackBottom.Set( 128, 128, 128) ;
// GeomData
m_pGeomDB = nullptr ;
m_colDef.Set( 0, 0, 0) ;
// Extension
SetExtension( BBox3d( -MIN_EXTENSION, -MIN_EXTENSION, -MIN_EXTENSION,
MIN_EXTENSION, MIN_EXTENSION, MIN_EXTENSION)) ;
// WinRect
m_bOutlineWR = true ;
m_colorWR.Set( 0, 0, 0) ;
m_bWinRect = false ;
}
//----------------------------------------------------------------------------
Scene::~Scene( void)
{
}
//----------------------------------------------------------------------------
bool
Scene::Init( IGeomDB* pGeomDB)
{
m_pGeomDB = pGeomDB ;
return true ;
}
//----------------------------------------------------------------------------
bool
Scene::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( GetEGrLogger(), "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] = 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( GetEGrLogger(), "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( GetEGrLogger(), "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( GetEGrLogger(), "OpenGL old way rendering !")
// reset stato di errore di OpenGL
glGetError() ;
return true ;
}
//----------------------------------------------------------------------------
int
Scene::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
Scene::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
Scene::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
Scene::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
Scene::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
Scene::RedrawWindow( void)
{
HWND hWnd = ::WindowFromDC( m_hDC) ;
if ( hWnd == nullptr)
return false ;
return ( ::RedrawWindow( hWnd, nullptr, nullptr, RDW_INVALIDATE | RDW_UPDATENOW) != 0) ;
}
//----------------------------------------------------------------------------
bool
Scene::SetExtension( const BBox3d& b3Ext)
{
if ( b3Ext.IsEmpty())
m_b3ExtWorld.Set( -MIN_EXTENSION, -MIN_EXTENSION, -MIN_EXTENSION,
MIN_EXTENSION, MIN_EXTENSION, MIN_EXTENSION) ;
else
m_b3ExtWorld = b3Ext ;
m_bExtViewOk = false ;
return true ;
}
//----------------------------------------------------------------------------
bool
Scene::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 ;
if ( ! CalcCameraFrame( frView))
return false ;
// calcolo l'estensione nel riferimento di vista
m_b3ExtView = m_b3ExtWorld ;
m_b3ExtView.ToLoc( frView) ;
m_bExtViewOk = true ;
return m_bExtViewOk ;
}
//----------------------------------------------------------------------------
bool
Scene::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
Scene::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( GetEGrLogger(), 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
Scene::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.1 ;
double dExtent = __max( ( EXP_COEFF * vtExtent.z), MIN_ZCLIP_EXT) ;
m_dZNear = - ( ptCenter.z + dExtent) ;
m_dZFar = - ( ptCenter.z - dExtent) ;
return true ;
}
//----------------------------------------------------------------------------
bool
Scene::Reshape( int nW, int nH)
{
if ( ! MakeCurrent())
return false ;
// 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( GetEGrLogger(), sOut.c_str())
}
// aggiorno
AdjustDimView( m_dHalfWidth, m_dHalfHeight) ;
// ridisegno
return Draw() ;
}
//----------------------------------------------------------------------------
bool
Scene::SetBackground( Color BackTop, Color BackBottom)
{
m_BackTop = BackTop ;
m_BackBottom = BackBottom ;
return true ;
}
//----------------------------------------------------------------------------
bool
Scene::Background( void)
{
// imposto il rendering corrente
if ( ! MakeCurrent())
return false ;
// cancello lo Zbuffer
glClearDepth( 1) ;
glClear( GL_DEPTH_BUFFER_BIT) ;
// se lo sfondo ha un colore uniforme
if ( m_BackTop == m_BackBottom) {
// imposto il colore dello sfondo e lo cancello
glClearColor( m_BackTop.GetRed(), m_BackTop.GetGreen(), m_BackTop.GetBlue(), m_BackTop.GetAlpha()) ;
glClear( GL_COLOR_BUFFER_BIT) ;
return true ;
}
// rendo neutre matrici di proiezione e di modello/vista
glMatrixMode( GL_PROJECTION) ;
glLoadIdentity() ;
glMatrixMode( GL_MODELVIEW) ;
glLoadIdentity() ;
// disabilito lo Zdepth
glDisable( GL_DEPTH_TEST) ;
// disegno lo sfondo con due colori
if ( ! m_bNewWay) {
glBegin( GL_TRIANGLE_STRIP) ;
glColor3f( m_BackBottom.GetRed(), m_BackBottom.GetGreen(), m_BackBottom.GetBlue()) ;
glVertex3f( -1, -1, 0.5) ;
glVertex3f( 1, -1, 0.5) ;
glColor3f( m_BackTop.GetRed(), m_BackTop.GetGreen(), m_BackTop.GetBlue()) ;
glVertex3f( -1, 1, 0.5) ;
glVertex3f( 1, 1, 0.5) ;
glEnd() ;
}
else {
unsigned int nVaoId ;
unsigned int nVboId ;
// definizione
glGenVertexArrays( 1, &nVaoId) ;
if ( nVaoId == 0)
return false ;
glBindVertexArray( nVaoId) ;
glGenBuffers( 1, &nVboId) ;
glBindBuffer( GL_ARRAY_BUFFER, nVboId) ;
glBufferData( GL_ARRAY_BUFFER, 8 * SIZEV3F, NULL, GL_STATIC_DRAW) ;
glVertexPointer( 3, GL_FLOAT, 2 * SIZEV3F, ((void*)(0))) ;
glEnableClientState( GL_VERTEX_ARRAY) ;
glColorPointer( 3, GL_FLOAT, 2 * SIZEV3F, ((void*)(1 * SIZEV3F))) ;
glEnableClientState( GL_COLOR_ARRAY) ;
Vert3f v3V ;
Vert3f v3C ;
// bottom left
v3V.Set( -1, -1, 0.5) ;
glBufferSubData( GL_ARRAY_BUFFER, 0 * SIZEV3F, SIZEV3F, &v3V) ;
v3C.Set( m_BackBottom.GetRed(), m_BackBottom.GetGreen(), m_BackBottom.GetBlue()) ;
glBufferSubData( GL_ARRAY_BUFFER, 1 * SIZEV3F, SIZEV3F, &v3C) ;
// bottom right
v3V.Set( 1, -1, 0.5) ;
glBufferSubData( GL_ARRAY_BUFFER, 2 * SIZEV3F, SIZEV3F, &v3V) ;
// v3C constant
glBufferSubData( GL_ARRAY_BUFFER, 3 * SIZEV3F, SIZEV3F, &v3C) ;
// top left
v3V.Set( -1, 1, 0.5) ;
glBufferSubData( GL_ARRAY_BUFFER, 4 * SIZEV3F, SIZEV3F, &v3V) ;
v3C.Set( m_BackTop.GetRed(), m_BackTop.GetGreen(), m_BackTop.GetBlue()) ;
glBufferSubData( GL_ARRAY_BUFFER, 5 * SIZEV3F, SIZEV3F, &v3C) ;
// top right
v3V.Set( 1, 1, 0.5) ;
glBufferSubData( GL_ARRAY_BUFFER, 6 * SIZEV3F, SIZEV3F, &v3V) ;
// v3C constant
glBufferSubData( GL_ARRAY_BUFFER, 7 * SIZEV3F, SIZEV3F, &v3C) ;
// disegno
glDrawArrays( GL_TRIANGLE_STRIP, 0, 4) ;
// cancellazione
glBindBuffer( GL_ARRAY_BUFFER, 0) ;
glDeleteBuffers( 1, &nVboId) ;
glBindVertexArray( 0) ;
glDeleteVertexArrays( 1, &nVaoId) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
Scene::Prepare( void)
{
// imposto il rendering corrente
if ( ! MakeCurrent())
return false ;
// 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( GetEGrLogger(), sOut.c_str())
}
return true ;
}
//----------------------------------------------------------------------------
bool
Scene::Draw( void)
{
// sistemo lo sfondo e lo Zbuffer
if ( ! Background())
return false ;
// imposto la camera
if ( ! Prepare())
return false ;
// imposto l'utilizzo dello Zbuffer
glDepthFunc( GL_LESS) ;
glEnable( GL_DEPTH_TEST) ;
// aggiorno il colore di default
if ( m_pGeomDB != nullptr)
m_pGeomDB->GetDefaultColor( m_colDef) ;
// imposto la dimensione standard dei punti
glPointSize( 3) ;
// disegno le geometrie del DB
DrawGroup( GDB_ID_ROOT, GDB_MD_STD, GDB_ST_ON) ;
// aggiungo disegni diretti (senza test Zbuffer)
glDisable( GL_DEPTH_TEST) ;
DrawWinRect() ;
// aggiorno
glFlush() ;
// verifico presenza errori
GLenum nErr = glGetError() ;
if ( nErr != GL_NO_ERROR) {
string sOut = "Draw OpenGL error " + ToString( (int)nErr) ;
LOG_INFO( GetEGrLogger(), sOut.c_str())
}
// scambio i buffer back e front ( eseguita solo se previsti)
if ( ! SwapBuffers( m_hDC))
LOG_INFO( GetEGrLogger(), "Draw SwapBuffers error")
return true ;
}
/*------------------------------------------------------------------------------------------*/
bool
Scene::Project( const Point3d& ptWorld, Point3d& ptView)
{
if ( ! MakeCurrent())
return false ;
// recupero le matrici
GLdouble ModelView[ 16] ;
glGetDoublev( GL_MODELVIEW_MATRIX, ModelView) ;
GLdouble Projection[ 16] ;
glGetDoublev( GL_PROJECTION_MATRIX, Projection) ;
GLint Viewport[ 4] ;
glGetIntegerv( GL_VIEWPORT, Viewport) ;
// eseguo la proiezione
// l'asse y della vista OpenGL va in alto con l'origine in basso,
// quello di Windows va in basso con l'origine in alto
int nRes =gluProject( ptWorld.x, ptWorld.y, ptWorld.z,
ModelView, Projection, Viewport,
&ptView.x, &ptView.y, &ptView.z) ;
ptView.y = (double) Viewport[3] - ptView.y ;
return ( nRes == GL_TRUE) ;
}
/*------------------------------------------------------------------------------------------*/
bool
Scene::UnProject( const Point3d& ptView, Point3d& ptWorld)
{
if ( ! MakeCurrent())
return false ;
// recupero le matrici
GLdouble ModelView[ 16] ;
glGetDoublev( GL_MODELVIEW_MATRIX, ModelView) ;
GLdouble Projection[ 16] ;
glGetDoublev( GL_PROJECTION_MATRIX, Projection) ;
GLint Viewport[ 4] ;
glGetIntegerv( GL_VIEWPORT, Viewport) ;
// eseguo la contro proiezione
// l'asse y della vista OpenGL va in alto con l'origine in basso,
// quello di Windows va in basso con l'origine in alto
int nRes = gluUnProject( ptView.x, ((double) Viewport[3] - ptView.y), ptView.z,
ModelView, Projection, Viewport,
&ptWorld.x, &ptWorld.y, &ptWorld.z) ;
return ( nRes == GL_TRUE) ;
}
//----------------------------------------------------------------------------
void
Scene::Destroy( void)
{
// cancellazione eventuali ObjEgrGraphics attaccati a oggetti geometrici
DeleteObjGraphicsGroup( GDB_ID_ROOT) ;
// cancellazione rendering context
wglMakeCurrent( nullptr, nullptr) ;
if ( m_hRC != nullptr) {
wglDeleteContext( m_hRC) ;
m_hRC = nullptr ;
}
}