Files
EgtGraphics/SceneSelect.cpp
T
Dario Sassi 6526f7ab9f EgtGraphics 1.6b5 :
- modifiche per gestione superfici trasparenti
- migliorata gestione colore da padre.
2015-02-17 22:45:57 +00:00

341 lines
10 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 2013-2014
//----------------------------------------------------------------------------
// File : SceneSelect.cpp Data : 26.11.14 Versione : 1.5k5
// Contenuto : Implementazione della selezione nella scena.
//
//
//
// Modifiche : 26.11.14 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "Scene.h"
#include "GraphObjs.h"
#include "DllMain.h"
#include "/EgtDev/Include/EgkGeoPoint3d.h"
#include "/EgtDev/Include/EgkGeoVector3d.h"
#include "/EgtDev/Include/EGkFrame3d.h"
#include "/EgtDev/Include/EGkCurve.h"
#include "/EgtDev/Include/EGkDistPointCurve.h"
#include "/EgtDev/Include/EGkExtText.h"
#include "/EgtDev/Include/EGkGdbConst.h"
#include "/EgtDev/Include/EGkGeomDB.h"
#include <algorithm>
using namespace std ;
//----------------------------------------------------------------------------
int
CompareSelRec( const void* pSr1, const void* pSr2)
{
if ( ((SelRec*)pSr1)->nZmin > ((SelRec*)pSr2)->nZmin)
return 1 ;
else if ( ((SelRec*)pSr1)->nZmin < ((SelRec*)pSr2)->nZmin)
return - 1 ;
else {
if ( ((SelRec*)pSr1)->nId > ((SelRec*)pSr2)->nId)
return 1 ;
else if ( ((SelRec*)pSr1)->nId < ((SelRec*)pSr2)->nId)
return - 1 ;
else
return 0 ;
}
}
//----------------------------------------------------------------------------
bool
Scene::Select( const Point3d& ptSelCenter, int nW, int nH, int& nSel)
{
// inizializzo selezione
m_bSelect = true ;
m_ptSelCent = ptSelCenter ;
m_nSelW = abs( nW) ;
m_nSelH = abs( nH) ;
m_nSelNbr = 0 ;
// se una delle due dimensioni è nulla, non posso selezionare alcunché
if ( m_nSelW == 0 || m_nSelH == 0) {
m_bSelect = false ;
nSel = m_nSelNbr ;
return true ;
}
// sfondo e Zbuffer non interessano
// imposto la camera, riducendo la viewport all'area di selezione
if ( ! Prepare()) {
m_bSelect = false ;
nSel = m_nSelNbr ;
return false ;
}
// imposto modalità di selezione
glSelectBuffer( DIM_SEL_BUF, (GLuint*)m_nSelBuff) ;
glRenderMode( GL_SELECT) ;
// inizializzo stack dei nomi
glInitNames() ;
glPushName( 0) ;
// eseguo disegno
// disabilito illuminazione
glDisable( GL_LIGHTING) ;
// non imposto glPolygonMode secondo il tipo di rendering perchè ignorato in selezione
// 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)) ;
// pulisco stack nomi
glPopName() ;
// chiudo modalità selezione, recupero buffer ripristino le matrici di OpenGL
m_nSelNbr = glRenderMode( GL_RENDER) ;
if ( m_nSelNbr < 0)
m_nSelNbr = DIM_SEL_BUF ;
m_bSelect = false ;
Prepare() ;
// riordino il buffer di selezione secondo la Zdepth minima crescente
qsort( m_nSelBuff, m_nSelNbr, sizeof( SelRec), CompareSelRec) ;
nSel = m_nSelNbr ;
return true ;
}
//----------------------------------------------------------------------------
bool
Scene::GetSelectedObjs( INTVECTOR& nIds)
{
// inizializzo vettore Id
nIds.clear() ;
try { nIds.reserve( m_nSelNbr) ; }
catch(...) { return false ; }
// inserisco l'Id degli oggetti selezionati
for ( int i = 0 ; i < m_nSelNbr ; ++ i)
nIds.push_back( m_nSelBuff[i].nId) ;
return true ;
}
//----------------------------------------------------------------------------
int
Scene::GetFirstSelectedObj( void)
{
m_nSelCurr = - 1 ;
return GetNextSelectedObj() ;
}
//----------------------------------------------------------------------------
int
Scene::GetNextSelectedObj( void)
{
// fuori dal range
m_nSelCurr ++ ;
if ( m_nSelCurr < 0 || m_nSelCurr >= m_nSelNbr)
return GDB_ID_NULL ;
return m_nSelBuff[m_nSelCurr].nId ;
}
//----------------------------------------------------------------------------
double
Scene::GetSelectedObjWinZ( int nSel)
{
if ( nSel < 0)
nSel = m_nSelCurr ;
if ( nSel < 0 || nSel >= m_nSelNbr)
return 0.5 ;
return 0.5 * ( double( m_nSelBuff[nSel].nZmin) + double( m_nSelBuff[nSel].nZmax)) / UINT_MAX ;
}
/*------------------------------------------------------------------------------------------*/
bool
Scene::UnselectableAdd( int nId)
{
// non si ammettono radice e id negativi
if ( nId <= GDB_ID_ROOT)
return false ;
// inserisco l'elemento
m_Unsel.push_back( nId) ;
// ordino in senso crescente
stable_sort( m_Unsel.begin(), m_Unsel.end()) ;
return true ;
}
/*------------------------------------------------------------------------------------------*/
bool
Scene::UnselectableRemove( int nId)
{
// non si ammettono radice e id negativi
if ( nId <= GDB_ID_ROOT)
return false ;
// cerco l'elemento
INTVECTOR::iterator Iter = find( m_Unsel.begin(), m_Unsel.end(), nId) ;
if ( Iter == m_Unsel.end())
return true ;
m_Unsel.erase( Iter) ;
return true ;
}
/*------------------------------------------------------------------------------------------*/
bool
Scene::UnselectableClearAll( void)
{
// cancello tutto
m_Unsel.clear() ;
return true ;
}
/*------------------------------------------------------------------------------------------*/
bool
Scene::UnselectableFind( int nId)
{
// eseguo ricerca su vettore ordinato in senso crescente
return binary_search( m_Unsel.begin(), m_Unsel.end(), nId) ;
}
/*------------------------------------------------------------------------------------------*/
bool
Scene::GetPointFromSelect( int nSelId, const Point3d& ptView, Point3d& ptSel)
{
// recupera il punto di mira proiettato sull'oggetto appena selezionato
// (va eseguito subito dopo la Select da cui si è derivato l'Id)
// è simile a GetSelectedSnapPoint
// rendo corrente l'entità selezionata
bool bFound = false ;
for ( int nId = GetFirstSelectedObj() ; nId != GDB_ID_NULL ; nId = GetNextSelectedObj()) {
if ( nId == nSelId) {
bFound = true ;
break ;
}
}
if ( ! bFound)
return false ;
// verifico sia entità geometrica
const IGeoObj* pGObj ;
if ( ( pGObj = m_pGeomDB->GetGeoObj( nSelId)) == nullptr)
return false ;
// recupero riferimento dell'entità
Frame3d frEnt ;
if ( ! m_pGeomDB->GetGlobFrame( nSelId, frEnt))
return false ;
// se punto
if ( pGObj->GetType() == GEO_PNT3D) {
// recupero il geo-punto
const IGeoPoint3d* pGP = GetGeoPoint3d( pGObj) ;
// recupero il punto
ptSel = pGP->GetPoint() ;
ptSel.ToGlob( frEnt) ;
}
// se vettore
else if ( pGObj->GetType() == GEO_VECT3D) {
// recupero il geo-vettore
const IGeoVector3d* pGV = GetGeoVector3d( pGObj) ;
// recupero il punto
ptSel = pGV->GetBase() ;
ptSel.ToGlob( frEnt) ;
}
// se frame
else if ( pGObj->GetType() == GEO_FRAME3D) {
// recupero il geo-frame
const IGeoFrame3d* pGF = GetGeoFrame3d( pGObj) ;
// recupero il punto
ptSel = pGF->GetFrame().Orig() ;
ptSel.ToGlob( frEnt) ;
}
// se curva
else if ( ( pGObj->GetType() & GEO_CURVE) != 0) {
// recupero la curva
const ICurve* pCrv = GetCurve( pGObj) ;
// il punto di riferimento deriva da XY su viewport e Z da selezione
Point3d ptWinZ( ptView.x, ptView.y, GetSelectedObjWinZ()) ;
// lo porto da spazio grafico a spazio geometrico globale
Point3d ptRef ;
UnProject( ptWinZ, ptRef) ;
// lo porto nel frame della curva
ptRef.ToLoc( frEnt) ;
// determino il punto più vicino della curva a questo
double dMinSqDist = INFINITO * INFINITO ;
MinDistPCInfo mdInfo ;
DistPointCurve dstPtCurve( ptRef, *pCrv) ;
if ( dstPtCurve.GetMinDistInfo( 0, mdInfo)) {
Point3d ptP = mdInfo.ptQ ;
ptP.ToGlob( frEnt) ;
if ( VerifySnapPoint( ptP, ptView, dMinSqDist))
ptSel = ptP ;
}
// eventuale verifica dell'estruso
double dTh ;
Vector3d vtExtr ;
if ( pCrv->GetExtrusion( vtExtr) && ! vtExtr.IsSmall() &&
pCrv->GetThickness( dTh) && fabs( dTh) > EPS_SMALL) {
vtExtr *= dTh ;
vtExtr.ToGlob( frEnt) ;
// correggo il punto di riferimento del contrario dell'estrusione
Vector3d vtTemp = vtExtr ;
vtTemp.ToLoc( frEnt) ;
// determino il punto più vicino della curva a questo
MinDistPCInfo mdInfo ;
DistPointCurve dstPtCurve( ptRef - vtTemp, *pCrv) ;
if ( dstPtCurve.GetMinDistInfo( 0, mdInfo)) {
Point3d ptP = mdInfo.ptQ ;
ptP.ToGlob( frEnt) ;
ptP += vtExtr ;
if ( VerifySnapPoint( ptP, ptView, dMinSqDist))
ptSel = ptP ;
}
}
}
// se testo
else if ( pGObj->GetType() == EXT_TEXT) {
// recupero il testo
const IExtText* pTxt = GetExtText( pGObj) ;
// cerco il punto
double dMinSqDist = INFINITO * INFINITO ;
Point3d ptP ;
// punto iniziale
if ( pTxt->GetStartPoint( ptP)) {
ptP.ToGlob( frEnt) ;
if ( VerifySnapPoint( ptP, ptView, dMinSqDist))
ptSel = ptP ;
}
// punto sopra iniziale
if ( pTxt->GetOverStartPoint( ptP)) {
ptP.ToGlob( frEnt) ;
if ( VerifySnapPoint( ptP, ptView, dMinSqDist))
ptSel = ptP ;
}
// punto finale
if ( pTxt->GetEndPoint( ptP)) {
ptP.ToGlob( frEnt) ;
if ( VerifySnapPoint( ptP, ptView, dMinSqDist))
ptSel = ptP ;
}
// punto sopra finale
if ( pTxt->GetOverEndPoint( ptP)) {
ptP.ToGlob( frEnt) ;
if ( VerifySnapPoint( ptP, ptView, dMinSqDist))
ptSel = ptP ;
}
// punto medio
if ( pTxt->GetMidPoint( ptP)) {
ptP.ToGlob( frEnt) ;
if ( VerifySnapPoint( ptP, ptView, dMinSqDist))
ptSel = ptP ;
}
// centro
if ( pTxt->GetCenterPoint( ptP)) {
ptP.ToGlob( frEnt) ;
if ( VerifySnapPoint( ptP, ptView, dMinSqDist))
ptSel = ptP ;
}
}
return true ;
}