4081ff7830
- aggiunta gestione disegno grid asimmetrica, impostabile con SetGridGeoAdv.
929 lines
29 KiB
C++
929 lines
29 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.
|
|
// 21.10.14 DS Aggiunta gestione Unselectable.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
//--------------------------- Include ----------------------------------------
|
|
#include "stdafx.h"
|
|
#include "Scene.h"
|
|
#include "GraphObjs.h"
|
|
#include "DllMain.h"
|
|
#include "/EgtDev/Include/EGrDllMain.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"
|
|
#include "/EgtDev/Include/SELkKeyProc.h"
|
|
#include "/EgtDev/Include/EgtKeyCodes.h"
|
|
|
|
using namespace std ;
|
|
|
|
//--------------------------- Constants --------------------------------------
|
|
static const double MIN_EXTENSION = 250 ;
|
|
static const double MIN_W_H = 0.01 ;
|
|
static const double MIN_ZCLIP_EXT = 25000 ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
IEGrScene*
|
|
CreateEGrScene( void)
|
|
{
|
|
// verifico la chiave e le opzioni
|
|
if ( ! VerifyKey( 0))
|
|
return nullptr ;
|
|
// creo l'oggetto
|
|
return static_cast<IEGrScene*> ( new(nothrow) Scene) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
Scene::Scene( void)
|
|
{
|
|
// Context data
|
|
m_hDC = nullptr ;
|
|
m_hRC = nullptr ;
|
|
m_nOglVer = 0 ;
|
|
m_bNewWay = false ;
|
|
// Camera e viewport
|
|
m_ptCenter = ORIG ;
|
|
SetCamera( 0, 0, 0) ;
|
|
m_nViewportW = 0 ;
|
|
m_nViewportH = 0 ;
|
|
// Textures
|
|
m_TextMgr.SetScene( this) ;
|
|
// Sfondo
|
|
m_colBackTop.Set( 176, 176, 176) ;
|
|
m_colBackBottom.Set( 176, 176, 176) ;
|
|
// Modalità di visualizzazione
|
|
m_nShowMode = SM_WIREFRAME ;
|
|
m_bShowCurveDirection = false ;
|
|
m_bShowTriaAdvanced = true ;
|
|
m_nShowZmap = ZSM_SURF ;
|
|
m_nShowText = TXT_FILL ;
|
|
// PointSize - LineWidth
|
|
m_dPointSize = 3 ;
|
|
m_dSelPointSize = 5 ;
|
|
m_dMarkPointSize = 7 ;
|
|
m_dLineWidth = 1 ;
|
|
m_dSelLineWidth = 2 ;
|
|
m_dMarkLineWidth = 5 ;
|
|
m_dGridLineWidth = 1 ;
|
|
m_dFrameLineWidth = 2 ;
|
|
// Selezione
|
|
m_bSelect = false ;
|
|
m_nObjFilterForSelect = GEO_ZERODIM | GEO_CURVE | GEO_SURF | GEO_VOLUME | GEO_EXTRA ;
|
|
m_Unsel.reserve( 50) ;
|
|
m_nSelCurr = GDB_ID_NULL ;
|
|
// Snap Punti
|
|
m_nLastSnapId = GDB_ID_NULL ;
|
|
m_bLastSnapDirOk = false ;
|
|
// GeomData
|
|
m_pGeomDB = nullptr ;
|
|
m_colDef.Set( 0, 0, 0) ;
|
|
m_colMark.Set( 255, 255, 0) ;
|
|
m_colSelSurf.Set( 255, 255, 192) ;
|
|
// Superfici semitrasparenti
|
|
m_vAlphaSurf.reserve( 100) ;
|
|
// Extension
|
|
SetExtension( BBox3d( -MIN_EXTENSION, -MIN_EXTENSION, -MIN_EXTENSION,
|
|
MIN_EXTENSION, MIN_EXTENSION, MIN_EXTENSION)) ;
|
|
// Grid
|
|
m_bShowGrid = false ;
|
|
m_bShowFrame = false ;
|
|
m_dSnapStep = 10 ;
|
|
m_nMinLineSstep = 1 ;
|
|
m_nMajLineSstep = 10 ;
|
|
m_nExtSstep = 100 ;
|
|
m_dGridMinX = -INFINITO ;
|
|
m_dGridMaxX = INFINITO ;
|
|
m_dGridMinY = -INFINITO ;
|
|
m_dGridMaxY = INFINITO ;
|
|
m_colMinLine.Set( 160, 160, 160) ;
|
|
m_colMajLine.Set( 160, 160, 160) ;
|
|
// Global Frame
|
|
m_bShowGlobFrame = false ;
|
|
// Direct
|
|
m_colorGL.Set( 255, 0, 0) ;
|
|
m_bGeoLine = false ;
|
|
m_colorGT.Set( 255, 0, 0) ;
|
|
m_bGeoTria = false ;
|
|
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 !")
|
|
|
|
// determino la versione di OpenGL
|
|
m_nOglVer = 0 ;
|
|
const char* p ;
|
|
if ( ( p = reinterpret_cast<const char*> ( glGetString( GL_VERSION))) != nullptr) {
|
|
string sOglVer = p ;
|
|
STRVECTOR vsTok ;
|
|
Tokenize( sOglVer, ".", vsTok) ;
|
|
if ( vsTok.size() >= 2) {
|
|
int nMaj, nMin ;
|
|
if ( FromString( vsTok[0], nMaj) && FromString( vsTok[1], nMin))
|
|
m_nOglVer = 10 * nMaj + nMin ;
|
|
}
|
|
}
|
|
|
|
// 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) const
|
|
{
|
|
// se RC della scena non è definito, errore
|
|
if ( m_hRC == nullptr)
|
|
return false ;
|
|
|
|
// se RC della scena è quello corrente, ok
|
|
HGLRC hRC = wglGetCurrentContext() ;
|
|
if ( m_hRC == hRC)
|
|
return true ;
|
|
|
|
// impost RC della scena
|
|
return ( wglMakeCurrent( m_hDC, m_hRC) != 0) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
string
|
|
Scene::GetOpenGLInfo( void) const
|
|
{
|
|
string sInfo = "OpenGL " ;
|
|
|
|
if ( MakeCurrent()) {
|
|
const char* p ;
|
|
if ( ( p = reinterpret_cast<const char*> ( glGetString( GL_VERSION))) != nullptr)
|
|
sInfo += p ;
|
|
sInfo += ( m_bNewWay ? " (Nw)" : " (Ow)") ;
|
|
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) const
|
|
{
|
|
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) const
|
|
{
|
|
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( abs( ptMin.x), abs( ptMax.x)) ;
|
|
double dHalfHeight = COEFF * max( abs( ptMin.y), abs( 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())
|
|
}
|
|
}
|
|
|
|
// verifico minimo delle dimensioni
|
|
dHalfWidth = max( dHalfWidth, MIN_W_H) ;
|
|
dHalfHeight = max( dHalfHeight, MIN_W_H) ;
|
|
|
|
// 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::Resize( 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 colBackTop, Color colBackBottom)
|
|
{
|
|
m_colBackTop = colBackTop ;
|
|
m_colBackBottom = colBackBottom ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Scene::GetBackground( Color& colBackTop, Color& colBackBottom)
|
|
{
|
|
colBackTop = m_colBackTop ;
|
|
colBackBottom = m_colBackBottom ;
|
|
|
|
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_colBackTop == m_colBackBottom) {
|
|
// imposto il colore dello sfondo e lo cancello
|
|
glClearColor( m_colBackTop.GetRed(), m_colBackTop.GetGreen(), m_colBackTop.GetBlue(), 1) ;
|
|
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) ;
|
|
|
|
// disabilito illuminazione
|
|
glDisable( GL_LIGHTING) ;
|
|
|
|
// imposto riempimento poligoni
|
|
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL) ;
|
|
|
|
// disegno lo sfondo con due colori
|
|
if ( ! m_bNewWay) {
|
|
glBegin( GL_TRIANGLE_STRIP) ;
|
|
glColor3f( m_colBackBottom.GetRed(), m_colBackBottom.GetGreen(), m_colBackBottom.GetBlue()) ;
|
|
glVertex3f( -1, -1, 0.5) ;
|
|
glVertex3f( 1, -1, 0.5) ;
|
|
glColor3f( m_colBackTop.GetRed(), m_colBackTop.GetGreen(), m_colBackTop.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_colBackBottom.GetRed(), m_colBackBottom.GetGreen(), m_colBackBottom.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_colBackTop.GetRed(), m_colBackTop.GetGreen(), m_colBackTop.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() ;
|
|
if ( m_bSelect) {
|
|
// recupero viewport
|
|
GLint Viewport[4] ;
|
|
glGetIntegerv( GL_VIEWPORT, Viewport) ;
|
|
// imposto area di pick
|
|
gluPickMatrix( m_ptSelCent.x, ( Viewport[3] - m_ptSelCent.y), m_nSelW, m_nSelH, Viewport) ;
|
|
}
|
|
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)
|
|
{
|
|
return MyDraw( true) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Scene::MyDraw( bool bSwapBF)
|
|
{
|
|
// sistemo lo sfondo e lo Zbuffer
|
|
if ( ! Background())
|
|
return false ;
|
|
|
|
// imposto la camera
|
|
if ( ! Prepare())
|
|
return false ;
|
|
|
|
// imposto l'utilizzo dello Zbuffer
|
|
glDepthFunc( GL_LEQUAL) ;
|
|
glEnable( GL_DEPTH_TEST) ;
|
|
|
|
// aggiorno il colore di default
|
|
if ( m_pGeomDB != nullptr)
|
|
m_pGeomDB->GetDefaultMaterial( m_colDef) ;
|
|
|
|
// impostazioni dipendenti dalla modalità di visualizzazione
|
|
switch ( m_nShowMode) {
|
|
case SM_WIREFRAME :
|
|
// disabilito illuminazione
|
|
glDisable( GL_LIGHTING) ;
|
|
// disegno griglia senza illuminazione (già impostato)
|
|
DrawGrid() ;
|
|
// imposto dati standard per punti e linee
|
|
glPointSize( (float) GetPointSize()) ;
|
|
glLineWidth( (float) GetLineWidth()) ;
|
|
// imposto disegno wireframe anche per poligoni
|
|
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE) ;
|
|
// disegno le geometrie del DB in una sola passata
|
|
DrawGroup( GDB_ID_ROOT, 1, MdStMkCol( GDB_MD_STD, GDB_ST_ON, GDB_MK_OFF, m_colDef)) ;
|
|
break ;
|
|
case SM_HIDDENLINE :
|
|
// disabilito illuminazione
|
|
glDisable( GL_LIGHTING) ;
|
|
// disegno griglia senza illuminazione (già impostato)
|
|
DrawGrid() ;
|
|
// imposto dati standard per punti e linee
|
|
glPointSize( (float) GetPointSize()) ;
|
|
glLineWidth( (float) GetLineWidth()) ;
|
|
// disegno le geometrie del DB
|
|
// prima passata per superfici solo per aggiornare Zbuffer (poligoni riempiti e offsettati)
|
|
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL) ;
|
|
glEnable( GL_POLYGON_OFFSET_FILL) ;
|
|
glPolygonOffset( 1.0, 1.0) ;
|
|
glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE) ;
|
|
DrawGroup( GDB_ID_ROOT, 1, MdStMkCol( GDB_MD_STD, GDB_ST_ON, GDB_MK_OFF, m_colDef)) ;
|
|
glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE) ;
|
|
glDisable( GL_POLYGON_OFFSET_FILL) ;
|
|
// seconda passata per tutto in forma 0dim e curve
|
|
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE) ;
|
|
DrawGroup( GDB_ID_ROOT, 2, MdStMkCol( GDB_MD_STD, GDB_ST_ON, GDB_MK_OFF, m_colDef)) ;
|
|
break ;
|
|
case SM_SHADING :
|
|
// disegno griglia senza illuminazione
|
|
glDisable( GL_LIGHTING) ;
|
|
DrawGrid() ;
|
|
// imposto dati standard per punti e linee
|
|
glPointSize( (float) GetPointSize()) ;
|
|
glLineWidth( (float) GetLineWidth()) ;
|
|
// imposto disegno shading per poligoni con davanti e dietro diversificati
|
|
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL) ;
|
|
glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE) ;
|
|
// imposto tipo shading
|
|
glShadeModel( GL_SMOOTH) ;
|
|
// imposto illuminazione
|
|
float LightAmbient[] = { 0.30f, 0.30f, 0.30f, 1.0f} ;
|
|
float LightDiff[] = { 0.40f, 0.40f, 0.40f, 1.0f} ;
|
|
float LightSpec[] = { 0.10f, 0.10f, 0.10f, 1.0f} ;
|
|
float Light0Pos[] = { 0.4f, 0.6f, 0.6f, 0.0f} ;
|
|
float Light1Pos[] = { -0.3f, -0.6f, 0.8f, 0.0f} ;
|
|
float Light2Pos[] = { -0.5f, 0.2f, -0.3f, 0.0f} ;
|
|
glEnable( GL_LIGHT0) ;
|
|
glLightfv( GL_LIGHT0, GL_AMBIENT, LightAmbient) ;
|
|
glLightfv( GL_LIGHT0, GL_DIFFUSE, LightDiff) ;
|
|
glLightfv( GL_LIGHT0, GL_SPECULAR, LightSpec) ;
|
|
glLightfv( GL_LIGHT0, GL_POSITION, Light0Pos) ;
|
|
glEnable( GL_LIGHT1) ;
|
|
glLightfv( GL_LIGHT1, GL_DIFFUSE, LightDiff) ;
|
|
glLightfv( GL_LIGHT1, GL_SPECULAR, LightSpec) ;
|
|
glLightfv( GL_LIGHT1, GL_POSITION, Light1Pos) ;
|
|
glEnable( GL_LIGHT2) ;
|
|
glLightfv( GL_LIGHT2, GL_DIFFUSE, LightDiff) ;
|
|
glLightfv( GL_LIGHT2, GL_SPECULAR, LightSpec) ;
|
|
glLightfv( GL_LIGHT2, GL_POSITION, Light2Pos) ;
|
|
// disegno le geometrie del DB
|
|
// annullo vettore superfici traslucide
|
|
m_vAlphaSurf.clear() ;
|
|
// prima passata per superfici completamente opache con illuminazione abilitata
|
|
glEnable( GL_POLYGON_OFFSET_FILL) ;
|
|
glPolygonOffset( 0.5, 0.5) ;
|
|
glEnable( GL_LIGHTING) ;
|
|
DrawGroup( GDB_ID_ROOT, 1, MdStMkCol( GDB_MD_STD, GDB_ST_ON, GDB_MK_OFF, m_colDef)) ;
|
|
glDisable( GL_POLYGON_OFFSET_FILL) ;
|
|
// seconda passata per 0dim e curve con illuminazione disabilitata
|
|
glDisable( GL_LIGHTING) ;
|
|
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE) ;
|
|
DrawGroup( GDB_ID_ROOT, 2, MdStMkCol( GDB_MD_STD, GDB_ST_ON, GDB_MK_OFF, m_colDef)) ;
|
|
// terza passata su vettore di superfici trasparenti con :
|
|
// illuminazione abilitata, blend abilitato e Zdepth solo in lettura
|
|
if ( m_vAlphaSurf.size() > 0) {
|
|
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL) ;
|
|
glEnable( GL_POLYGON_OFFSET_FILL) ;
|
|
glPolygonOffset( 0.5, 0.5) ;
|
|
glEnable( GL_LIGHTING) ;
|
|
glEnable( GL_BLEND) ;
|
|
glDepthMask( GL_FALSE) ;
|
|
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ;
|
|
DrawAlphaSurfVector() ;
|
|
m_vAlphaSurf.clear() ;
|
|
glDepthMask( GL_TRUE) ;
|
|
glDisable( GL_BLEND) ;
|
|
glDisable( GL_POLYGON_OFFSET_FILL) ;
|
|
}
|
|
break ;
|
|
}
|
|
|
|
// disabilito uso Zbuffer e illuminazione
|
|
glDisable( GL_DEPTH_TEST) ;
|
|
glDisable( GL_LIGHTING) ;
|
|
|
|
// disegno riferimento globale
|
|
DrawGlobFrame() ;
|
|
|
|
// aggiungo disegni diretti (con poligoni riempiti)
|
|
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL) ;
|
|
DrawDirect() ;
|
|
|
|
// 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 ( bSwapBF && ! SwapBuffers( m_hDC))
|
|
LOG_INFO( GetEGrLogger(), "Draw SwapBuffers error")
|
|
|
|
return true ;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------------------*/
|
|
bool
|
|
Scene::Project( const Point3d& ptWorld, Point3d& ptView) const
|
|
{
|
|
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) const
|
|
{
|
|
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 textures
|
|
if ( ! m_TextMgr.Clear())
|
|
LOG_ERROR( GetEGrLogger(), "Error unloading textures from OpenGl") ;
|
|
|
|
// cancellazione rendering context
|
|
wglMakeCurrent( nullptr, nullptr) ;
|
|
if ( m_hRC != nullptr) {
|
|
wglDeleteContext( m_hRC) ;
|
|
m_hRC = nullptr ;
|
|
}
|
|
}
|