00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 #include <stdlib.h>
00045 #include <stdio.h>
00046
00047 #include "OSGConfig.h"
00048
00049 #include <OSGLog.h>
00050 #include <OSGFieldContainer.h>
00051 #include <OSGFieldContainerPtr.h>
00052 #include <OSGNode.h>
00053 #include <OSGNodeCore.h>
00054 #include <OSGAction.h>
00055 #include <OSGRenderAction.h>
00056 #include <OSGWindow.h>
00057 #include <OSGCamera.h>
00058 #include <OSGViewport.h>
00059 #include <OSGBackground.h>
00060 #include <OSGGLEXT.h>
00061
00062 #include <OSGBaseFunctions.h>
00063
00064 #include <OSGDrawTreeNodeFactory.h>
00065
00066 #include <OSGMaterial.h>
00067 #include <OSGMultiPassMaterial.h>
00068 #include <OSGSwitchMaterial.h>
00069
00070 #include <OSGGeometry.h>
00071 #include <OSGSwitch.h>
00072 #include <OSGLog.h>
00073
00074 #include <OSGLight.h>
00075 #include <OSGLightEnv.h>
00076
00077 #include <OSGClipPlane.h>
00078
00079 #include <OSGGL.h>
00080 #include <OSGVolumeDraw.h>
00081 #include <OSGSimpleAttachments.h>
00082
00083 OSG_USING_NAMESPACE
00084
00085
00086
00087
00088
00096
00097
00098
00099
00100
00101
00102
00103
00104 char RenderAction::cvsid[] = "@(#)$Id: $";
00105
00106
00110 RenderAction *RenderAction::_pPrototype = NULL;
00111
00115 std::vector<Action::Functor> *RenderAction::_vDefaultEnterFunctors = NULL;
00116 std::vector<Action::Functor> *RenderAction::_vDefaultLeaveFunctors = NULL;
00117
00118
00119 StatElemDesc<StatTimeElem> RenderAction::statDrawTime("drawTime",
00120 "time for draw tree traversal");
00121 StatElemDesc<StatIntElem > RenderAction::statNMaterials("NMaterials",
00122 "number of material changes");
00123 StatElemDesc<StatIntElem > RenderAction::statNMatrices("NMatrices",
00124 "number of matrix changes");
00125 StatElemDesc<StatIntElem > RenderAction::statNLights("NLights",
00126 "number of light changes");
00127 StatElemDesc<StatIntElem > RenderAction::statNGeometries("NGeometries",
00128 "number of Geometry nodes");
00129 StatElemDesc<StatIntElem > RenderAction::statNTransGeometries("NTransGeometries",
00130 "number of transformed Geometry nodes");
00131 StatElemDesc<StatIntOnceElem > RenderAction::statNTextures("NTextures",
00132 "number of texture changes");
00133 StatElemDesc<StatIntOnceElem > RenderAction::statNTexBytes("NTexBytes",
00134 "sum of all used textures' sizes (approx., in bytes)");
00135 StatElemDesc<StatStringElem > RenderAction::statNOcclusionMode("OcclusionMode",
00136 "occlusion culling mode");
00137 StatElemDesc<StatIntElem > RenderAction::statNOcclusionTests("NOcclusionTests",
00138 "number of occlusion tests");
00139 StatElemDesc<StatIntElem > RenderAction::statNOcclusionCulled("NOcclusionCulled",
00140 "number of objects culled via occlusion culling");
00141
00142 UInt32 RenderAction::_arbOcclusionQuery;
00143 UInt32 RenderAction::_funcGenQueriesARB = Window::invalidFunctionID;
00144 UInt32 RenderAction::_funcDeleteQueriesARB = Window::invalidFunctionID;
00145 UInt32 RenderAction::_funcBeginQueryARB = Window::invalidFunctionID;
00146 UInt32 RenderAction::_funcEndQueryARB = Window::invalidFunctionID;
00147 UInt32 RenderAction::_funcGetQueryObjectuivARB = Window::invalidFunctionID;
00148
00149 const Int32 RenderAction::OcclusionStopAndWait = 1;
00150 const Int32 RenderAction::OcclusionMultiFrame = 2;
00151 const Int32 RenderAction::OcclusionHierarchicalMultiFrame = 6;
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00166 void RenderAction::registerEnterDefault(const FieldContainerType &type,
00167 const Action::Functor &func)
00168 {
00169 if(_vDefaultEnterFunctors == NULL)
00170 {
00171 _vDefaultEnterFunctors = new std::vector<Action::Functor>;
00172 }
00173
00174 while(type.getId() >= _vDefaultEnterFunctors->size())
00175 {
00176 _vDefaultEnterFunctors->push_back(
00177 osgTypedFunctionFunctor2CPtrRef<
00178 ResultE,
00179 CNodePtr,
00180 Action * >(&Action::_defaultEnterFunction));
00181 }
00182
00183 (*_vDefaultEnterFunctors)[type.getId()] = func;
00184 }
00185
00186 void RenderAction::registerLeaveDefault(const FieldContainerType &type,
00187 const Action::Functor &func)
00188 {
00189 if(_vDefaultLeaveFunctors == NULL)
00190 {
00191 _vDefaultLeaveFunctors = new std::vector<Action::Functor>;
00192 }
00193
00194 while(type.getId() >= _vDefaultLeaveFunctors->size())
00195 {
00196 _vDefaultLeaveFunctors->push_back(
00197 osgTypedFunctionFunctor2CPtrRef<
00198 ResultE,
00199 CNodePtr,
00200 Action * >(&Action::_defaultLeaveFunction));
00201 }
00202
00203 (*_vDefaultLeaveFunctors)[type.getId()] = func;
00204 }
00205
00206
00211 void RenderAction::setPrototype(RenderAction *pPrototype)
00212 {
00213 _pPrototype = pPrototype;
00214 }
00215
00216 RenderAction *RenderAction::getPrototype(void)
00217 {
00218 return _pPrototype;
00219 }
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00245 RenderAction::RenderAction(void) :
00246 Inherited (),
00247 _pNodeFactory (NULL),
00248
00249 _uiMatrixId (0),
00250 _currMatrix (),
00251 _vMatrixStack (),
00252
00253 _mMatMap (),
00254
00255 _pMatRoots (),
00256 _pTransMatRoots (),
00257 _pNoStateSortRoot (NULL),
00258 _pNoStateSortTransRoot(NULL),
00259
00260 _ocRoot (),
00261 _uiActiveMatrix (0),
00262 _pActiveState (NULL),
00263
00264 _uiNumMaterialChanges(0),
00265 _uiNumMatrixChanges (0),
00266 _uiNumLightChanges (0),
00267 _uiNumGeometries (0),
00268 _uiNumOcclusionTests (0),
00269 _uiNumOcclusionCulled(0),
00270 _uiNumTransGeometries(0),
00271
00272 _bSortTrans (true),
00273 _bZWriteTrans (false),
00274 _bLocalLights (false),
00275 _bCorrectTwoSidedLighting (false),
00276 _bOcclusionCulling (false),
00277 _occlusionCullingMode (OcclusionStopAndWait),
00278 _occlusionCullingPixels (0),
00279 _occlusionCullingThreshold(64),
00280 _currentOcclusionQueryIndex(0),
00281 _occluded_nodes (),
00282 _hier_occlusions (),
00283 _occ_bb_dl (0),
00284
00285 _bSmallFeatureCulling (false),
00286 _smallFeaturesPixels (10.0f),
00287 _smallFeaturesThreshold (32),
00288 _worldToScreenMatrix (),
00289
00290 _useGLFinish (true),
00291
00292 _vLights(),
00293 _lightsMap(),
00294 _lightsState(0),
00295 _activeLightsState(0),
00296 _activeLightsCount(0),
00297 _activeLightsMask(0),
00298
00299 _lightsTable(),
00300 _lightsPath(),
00301 _lightEnvsLightsState(),
00302
00303
00304 _vClipPlanes(),
00305 _clipPlanesMap(),
00306 _clipPlanesState(0),
00307 _activeClipPlanesState(0),
00308 _activeClipPlanesCount(0),
00309 _activeClipPlanesMask(0),
00310
00311 _clipPlanesTable(),
00312 _clipPlanesPath(),
00313
00314
00315 _stateSorting(true),
00316 _visibilityStack(),
00317
00318 _occlusionQuery (0),
00319 _occlusionQueriesPool (),
00320 _occlusionQueries (),
00321
00322 _glGenQueriesARB (NULL),
00323 _glDeleteQueriesARB (NULL),
00324 _glBeginQueryARB (NULL),
00325 _glEndQueryARB (NULL),
00326 _glGetQueryObjectuivARB (NULL),
00327
00328 _cgChunkId(-1),
00329 _cgfxChunkId(-1),
00330 _shlChunkId(-1)
00331 {
00332 if(_vDefaultEnterFunctors != NULL)
00333 _enterFunctors = *_vDefaultEnterFunctors;
00334
00335 if(_vDefaultLeaveFunctors != NULL)
00336 _leaveFunctors = *_vDefaultLeaveFunctors;
00337
00338 _pNodeFactory = new DrawTreeNodeFactory;
00339
00340 _arbOcclusionQuery = Window::registerExtension("GL_ARB_occlusion_query");
00341 _funcGenQueriesARB = Window::registerFunction (OSG_DLSYM_UNDERSCORE"glGenQueriesARB", _arbOcclusionQuery);
00342 _funcDeleteQueriesARB = Window::registerFunction (OSG_DLSYM_UNDERSCORE"glDeleteQueriesARB", _arbOcclusionQuery);
00343 _funcBeginQueryARB = Window::registerFunction (OSG_DLSYM_UNDERSCORE"glBeginQueryARB", _arbOcclusionQuery);
00344 _funcEndQueryARB = Window::registerFunction (OSG_DLSYM_UNDERSCORE"glEndQueryARB", _arbOcclusionQuery);
00345 _funcGetQueryObjectuivARB = Window::registerFunction (OSG_DLSYM_UNDERSCORE"glGetQueryObjectuivARB", _arbOcclusionQuery);
00346
00347
00348 StateChunkPtr cgChunk = StateChunkPtr::dcast(FieldContainerFactory::the()->createFieldContainer("CGChunk"));
00349 if(cgChunk != NullFC)
00350 {
00351 _cgChunkId = cgChunk->getClass()->getId();
00352 subRefCP(cgChunk);
00353 }
00354
00355
00356 StateChunkPtr cgfxChunk = StateChunkPtr::dcast(FieldContainerFactory::the()->createFieldContainer("CGFXChunk"));
00357 if(cgfxChunk != NullFC)
00358 {
00359 _cgfxChunkId = cgfxChunk->getClass()->getId();
00360 subRefCP(cgfxChunk);
00361 }
00362
00363 StateChunkPtr shlChunk = StateChunkPtr::dcast(FieldContainerFactory::the()->createFieldContainer("SHLChunk"));
00364 if(shlChunk != NullFC)
00365 {
00366 _shlChunkId = shlChunk->getClass()->getId();
00367 subRefCP(shlChunk);
00368 }
00369 }
00370
00371
00375 RenderAction::RenderAction(const RenderAction &source) :
00376 Inherited (source),
00377 _pNodeFactory (NULL),
00378
00379 _uiMatrixId (source._uiMatrixId),
00380 _currMatrix (source._currMatrix),
00381 _vMatrixStack (source._vMatrixStack),
00382
00383 _mMatMap (source._mMatMap),
00384
00385 _pMatRoots (source._pMatRoots),
00386 _pTransMatRoots (source._pTransMatRoots),
00387 _pNoStateSortRoot (source._pNoStateSortRoot),
00388 _pNoStateSortTransRoot(source._pNoStateSortTransRoot),
00389
00390 _ocRoot (source._ocRoot),
00391
00392 _uiActiveMatrix (source._uiActiveMatrix),
00393 _pActiveState (source._pActiveState),
00394
00395 _uiNumMaterialChanges(source._uiNumMaterialChanges),
00396 _uiNumMatrixChanges (source._uiNumMatrixChanges),
00397 _uiNumLightChanges (source._uiNumLightChanges),
00398 _uiNumGeometries (source._uiNumGeometries),
00399 _uiNumOcclusionTests (source._uiNumOcclusionTests),
00400 _uiNumOcclusionCulled(source._uiNumOcclusionCulled),
00401 _uiNumTransGeometries(source._uiNumTransGeometries),
00402
00403 _bSortTrans (source._bSortTrans),
00404 _bZWriteTrans (source._bZWriteTrans),
00405 _bLocalLights (source._bLocalLights),
00406 _bCorrectTwoSidedLighting (source._bCorrectTwoSidedLighting),
00407 _bOcclusionCulling (source._bOcclusionCulling),
00408 _occlusionCullingMode (source._occlusionCullingMode),
00409 _occlusionCullingPixels (source._occlusionCullingPixels),
00410 _occlusionCullingThreshold(source._occlusionCullingThreshold),
00411 _currentOcclusionQueryIndex(source._currentOcclusionQueryIndex),
00412 _occluded_nodes (source._occluded_nodes),
00413 _hier_occlusions (source._hier_occlusions),
00414 _occ_bb_dl (source._occ_bb_dl),
00415
00416 _bSmallFeatureCulling (source._bSmallFeatureCulling),
00417 _smallFeaturesPixels (source._smallFeaturesPixels),
00418 _smallFeaturesThreshold (source._smallFeaturesThreshold),
00419 _worldToScreenMatrix (source._worldToScreenMatrix),
00420
00421 _useGLFinish (source._useGLFinish),
00422
00423 _vLights (source._vLights),
00424 _lightsMap (source._lightsMap),
00425 _lightsState (source._lightsState),
00426 _activeLightsState (source._activeLightsState),
00427 _activeLightsCount (source._activeLightsCount),
00428 _activeLightsMask (source._activeLightsMask),
00429
00430 _lightsTable (source._lightsTable),
00431 _lightsPath (source._lightsPath),
00432 _lightEnvsLightsState(source._lightEnvsLightsState),
00433
00434
00435 _vClipPlanes (source._vClipPlanes),
00436 _clipPlanesMap (source._clipPlanesMap),
00437 _clipPlanesState (source._clipPlanesState),
00438 _activeClipPlanesState (source._activeClipPlanesState),
00439 _activeClipPlanesCount (source._activeClipPlanesCount),
00440 _activeClipPlanesMask (source._activeClipPlanesMask),
00441
00442 _clipPlanesTable (source._clipPlanesTable),
00443 _clipPlanesPath (source._clipPlanesPath),
00444
00445 _stateSorting (source._stateSorting),
00446 _visibilityStack (source._visibilityStack),
00447
00448 _occlusionQuery (source._occlusionQuery),
00449 _occlusionQueriesPool (source._occlusionQueriesPool),
00450 _occlusionQueries (source._occlusionQueries),
00451
00452 _glGenQueriesARB (source._glGenQueriesARB),
00453 _glDeleteQueriesARB (source._glDeleteQueriesARB),
00454 _glBeginQueryARB (source._glBeginQueryARB),
00455 _glEndQueryARB (source._glEndQueryARB),
00456 _glGetQueryObjectuivARB (source._glGetQueryObjectuivARB),
00457
00458 _cgfxChunkId(source._cgfxChunkId),
00459 _cgChunkId(source._cgChunkId),
00460 _shlChunkId(source._shlChunkId)
00461 {
00462 _pNodeFactory = new DrawTreeNodeFactory;
00463 }
00464
00468 RenderAction * RenderAction::create(void)
00469 {
00470 RenderAction *returnValue;
00471
00472 if(_pPrototype)
00473 {
00474 returnValue = new RenderAction(*_pPrototype);
00475 }
00476 else
00477 {
00478 returnValue = new RenderAction();
00479 }
00480
00481 return returnValue;
00482 }
00483
00484
00488 RenderAction::~RenderAction(void)
00489 {
00490 delete _pNodeFactory;
00491
00492 if(_occ_bb_dl != 0)
00493 glDeleteLists(_occ_bb_dl, 1);
00494
00495 if(_occlusionQuery != 0)
00496 _glDeleteQueriesARB(1, &_occlusionQuery);
00497 deleteOcclusionQueriesPool();
00498 }
00499
00500
00501
00502
00503
00504 void RenderAction::getMaterialStates(Material *mat, std::vector<State *> &states)
00505 {
00506 if(!mat->isMultiPass())
00507 {
00508 states.push_back(mat->getState().getCPtr());
00509 }
00510 else
00511 {
00512
00513 MultiPassMaterial *mmat = dynamic_cast<MultiPassMaterial *>(mat);
00514 if(mmat != NULL)
00515 {
00516
00517 UInt32 passes = mmat->getMaterials().getSize();
00518 if(passes > 0)
00519 {
00520 for(UInt32 i=0;i<passes;++i)
00521 {
00522 getMaterialStates(mmat->getMaterials(i).getCPtr(), states);
00523 }
00524 }
00525 else
00526 {
00527
00528
00529 passes = mmat->getNPasses();
00530 for(UInt32 i=0;i<passes;++i)
00531 states.push_back(mmat->getState(i).getCPtr());
00532 }
00533 }
00534 else
00535 {
00536 SwitchMaterial *swmat = dynamic_cast<SwitchMaterial *>(mat);
00537 if(swmat != NULL)
00538 {
00539 getMaterialStates(swmat->getCurrentMaterial().getCPtr(), states);
00540 }
00541 else
00542 {
00543 UInt32 passes = mat->getNPasses();
00544 for(UInt32 i=0;i<passes;++i)
00545 states.push_back(mat->getState(i).getCPtr());
00546 }
00547 }
00548 }
00549 }
00550
00551
00552
00553
00554 void RenderAction::dropGeometry(Geometry *pGeo)
00555 {
00556 Material *pMat;
00557 State *pState;
00558
00559 if(pGeo == NULL)
00560 {
00561 return;
00562 }
00563
00564 if(getMaterial() != NULL)
00565 {
00566 pMat = getMaterial();
00567 }
00568 else if(pGeo->getMaterial() != NullFC)
00569 {
00570 pMat = pGeo->getMaterial().getCPtr();
00571 }
00572 else
00573 {
00574 return;
00575 }
00576
00577 std::vector<State *> states;
00578 getMaterialStates(pMat, states);
00579
00580 UInt32 mpMatPasses = states.size();
00581 bool isMultiPass = (mpMatPasses > 1) || pMat->isMultiPass();
00582
00583 Int32 sortKey = pMat->getRealSortKey();
00584
00585 if(!_stateSorting ||
00586 (sortKey == Material::NoStateSorting &&
00587 (!_bSortTrans || !pMat->isTransparent())))
00588 {
00589 for(UInt32 mpi=0;mpi<mpMatPasses;++mpi)
00590 {
00591 pState = states[mpi];
00592
00593 DrawTreeNode *pNewElem = _pNodeFactory->create();
00594
00595 pNewElem->setNode (getActNode());
00596 pNewElem->setGeometry (pGeo);
00597 pNewElem->setMatrixStore(_currMatrix);
00598 pNewElem->setLightsState(_lightsState);
00599 pNewElem->setClipPlanesState(_clipPlanesState);
00600 pNewElem->setState(pState);
00601 if(sortKey == Material::NoStateSorting)
00602 pNewElem->setNoStateSorting();
00603
00604 if(isMultiPass)
00605 {
00606 if(mpi == mpMatPasses-1)
00607 pNewElem->setLastMultiPass();
00608 else
00609 pNewElem->setMultiPass();
00610 }
00611
00612 if(!pMat->isTransparent())
00613 {
00614 if(_pNoStateSortRoot == NULL)
00615 _pNoStateSortRoot = pNewElem;
00616 else
00617 _pNoStateSortRoot->addChild(pNewElem);
00618 }
00619 else
00620 {
00621 if(_pNoStateSortTransRoot == NULL)
00622 _pNoStateSortTransRoot = pNewElem;
00623 else
00624 _pNoStateSortTransRoot->addChild(pNewElem);
00625 }
00626 }
00627 return;
00628 }
00629
00630 MaterialMap::iterator it = _mMatMap.find(pMat);
00631
00632 #if 0
00633 pMat->rebuildState();
00634 #endif
00635
00636 if(sortKey == Material::NoStateSorting)
00637 sortKey = 0;
00638
00639 DrawTreeNode *pLastMultiPass = NULL;
00640
00641 for(UInt32 mpi=0;mpi<mpMatPasses;++mpi)
00642 {
00643 pState = states[mpi];
00644
00645 if(_bSortTrans && pMat->isTransparent())
00646 {
00647 DrawTreeNode *pNewElem = _pNodeFactory->create();
00648 Pnt3f objPos;
00649 getActNode()->getVolume().getCenter(objPos);
00650
00651 _currMatrix.second.mult(objPos);
00652
00653 pNewElem->setNode (getActNode());
00654
00655 pNewElem->setGeometry (pGeo);
00656 pNewElem->setMatrixStore(_currMatrix);
00657
00658 pNewElem->setState (pState);
00659 pNewElem->setScalar (objPos[2]);
00660 pNewElem->setLightsState(_lightsState);
00661 pNewElem->setClipPlanesState(_clipPlanesState);
00662
00663 if(isMultiPass)
00664 {
00665 if(mpi == mpMatPasses-1)
00666 pNewElem->setLastMultiPass();
00667 else
00668 pNewElem->setMultiPass();
00669 }
00670
00671 if(_pTransMatRoots.find(sortKey) == _pTransMatRoots.end())
00672 {
00673 TransSortMap ts;
00674 _pTransMatRoots.insert(std::make_pair(sortKey, ts));
00675 }
00676
00677 TransSortMap &ts = _pTransMatRoots[sortKey];
00678 TransSortMap::iterator it = ts.find(pNewElem->getScalar());
00679 if(it == ts.end())
00680 ts.insert(std::make_pair(pNewElem->getScalar(), pNewElem));
00681 else
00682 (*it).second->addChild(pNewElem);
00683
00684 _uiNumTransGeometries++;
00685 }
00686 else
00687 {
00688 DrawTreeNode *pNewElem = _pNodeFactory->create();
00689
00690 if(it == _mMatMap.end())
00691 {
00692 DrawTreeNode *pNewMatElem = _pNodeFactory->create();
00693
00694
00695 _mMatMap[pMat] = pNewMatElem;
00696
00697 pNewElem->setNode (getActNode());
00698 pNewElem->setGeometry (pGeo);
00699 pNewElem->setMatrixStore(_currMatrix);
00700 pNewElem->setLightsState(_lightsState);
00701 pNewElem->setClipPlanesState(_clipPlanesState);
00702
00703 if(isMultiPass)
00704 {
00705
00706
00707 pNewElem->setState(pState);
00708
00709 if(mpi == mpMatPasses-1)
00710 pNewElem->setLastMultiPass();
00711 else
00712 pNewElem->setMultiPass();
00713 }
00714 else
00715 {
00716
00717
00718 pNewMatElem->setState(pState);
00719 }
00720
00721 pNewMatElem->addChild(pNewElem);
00722 pNewMatElem->setNode(getActNode());
00723 pNewMatElem->setLightsState(_lightsState);
00724 pNewMatElem->setClipPlanesState(_clipPlanesState);
00725
00726 if(_pMatRoots.find(sortKey) == _pMatRoots.end())
00727 _pMatRoots.insert(std::make_pair(sortKey, _pNodeFactory->create()));
00728
00729 _pMatRoots[sortKey]->addChild(pNewMatElem);
00730 }
00731 else
00732 {
00733 pNewElem->setNode (getActNode());
00734 pNewElem->setGeometry (pGeo);
00735 pNewElem->setMatrixStore(_currMatrix);
00736 pNewElem->setLightsState(_lightsState);
00737 pNewElem->setClipPlanesState(_clipPlanesState);
00738
00739 if(isMultiPass)
00740 {
00741 pNewElem->setState(pState);
00742
00743 if(mpi == mpMatPasses-1)
00744 pNewElem->setLastMultiPass();
00745 else
00746 pNewElem->setMultiPass();
00747 }
00748
00749 it->second->addChild(pNewElem);
00750 }
00751 }
00752 }
00753 }
00754
00755 void RenderAction::dropFunctor(Material::DrawFunctor &func, Material *mat)
00756 {
00757 Material *pMat;
00758 State *pState;
00759
00760 if(getMaterial() != NULL)
00761 {
00762 pMat = getMaterial();
00763 }
00764 else if(mat != NULL)
00765 {
00766 pMat = mat;
00767 }
00768 else
00769 {
00770 return;
00771 }
00772
00773 std::vector<State *> states;
00774 getMaterialStates(pMat, states);
00775
00776 UInt32 mpMatPasses = states.size();
00777 bool isMultiPass = (mpMatPasses > 1) || pMat->isMultiPass();
00778
00779 Int32 sortKey = pMat->getRealSortKey();
00780
00781 if(_bOcclusionCulling && (_occlusionCullingMode & OcclusionStopAndWait) && _stateSorting)
00782 {
00783 DrawTreeNode *pLastMultiPass = NULL;
00784 for(UInt32 mpi=0;mpi<mpMatPasses;++mpi)
00785 {
00786 pState = states[mpi];
00787
00788 DrawTreeNode *pNewElem = _pNodeFactory->create();
00789
00790 pNewElem->setNode (getActNode());
00791 pNewElem->setFunctor (func);
00792 pNewElem->setMatrixStore(_currMatrix);
00793 pNewElem->setLightsState(_lightsState);
00794 pNewElem->setClipPlanesState(_clipPlanesState);
00795 pNewElem->setState (pState);
00796 if(sortKey == Material::NoStateSorting)
00797 pNewElem->setNoStateSorting();
00798
00799 if(isMultiPass)
00800 {
00801 if(mpi == mpMatPasses-1)
00802 pNewElem->setLastMultiPass();
00803 else
00804 pNewElem->setMultiPass();
00805 }
00806
00807 if(!pMat->isTransparent())
00808 {
00809 if(sortKey == 0)
00810 {
00811 Pnt3f objPos;
00812
00813
00814
00815
00816
00817
00818 DynamicVolume vol = getActNode()->getVolume();
00819 vol.transform(_currMatrix.second);
00820 objPos = vol.getMax();
00821
00822 pNewElem->setScalar(objPos[2]);
00823
00824 OCMap::iterator it = _ocRoot.find(pNewElem->getScalar());
00825 if(it == _ocRoot.end())
00826 _ocRoot.insert(std::make_pair(pNewElem->getScalar(), pNewElem));
00827 else
00828 (*it).second->addChild(pNewElem);
00829 }
00830 else
00831 {
00832 if(_pMatRoots.find(sortKey) == _pMatRoots.end())
00833 _pMatRoots.insert(std::make_pair(sortKey, _pNodeFactory->create()));
00834
00835 _pMatRoots[sortKey]->addChild(pNewElem);
00836 }
00837 }
00838 else
00839 {
00840 if(_bSortTrans)
00841 {
00842 Pnt3f objPos;
00843 getActNode()->getVolume().getCenter(objPos);
00844 _currMatrix.second.mult(objPos);
00845 pNewElem->setScalar(objPos[2]);
00846
00847 if(isMultiPass)
00848 {
00849 if(mpi == mpMatPasses-1)
00850 pNewElem->setLastMultiPass();
00851 else
00852 pNewElem->setMultiPass();
00853 }
00854
00855 if(_pTransMatRoots.find(sortKey) == _pTransMatRoots.end())
00856 {
00857 TransSortMap ts;
00858 _pTransMatRoots.insert(std::make_pair(sortKey, ts));
00859 }
00860
00861 TransSortMap &ts = _pTransMatRoots[sortKey];
00862 TransSortMap::iterator it = ts.find(pNewElem->getScalar());
00863 if(it == ts.end())
00864 ts.insert(std::make_pair(pNewElem->getScalar(), pNewElem));
00865 else
00866 (*it).second->addChild(pNewElem);
00867
00868 _uiNumTransGeometries++;
00869 }
00870 else
00871 {
00872 if(_pNoStateSortTransRoot == NULL)
00873 _pNoStateSortTransRoot = pNewElem;
00874 else
00875 _pNoStateSortTransRoot->addChild(pNewElem);
00876 }
00877 }
00878 }
00879 return;
00880 }
00881
00882 if(!_stateSorting ||
00883 (sortKey == Material::NoStateSorting &&
00884 (!_bSortTrans || !pMat->isTransparent())))
00885 {
00886 for(UInt32 mpi=0;mpi<mpMatPasses;++mpi)
00887 {
00888 pState = states[mpi];
00889
00890 DrawTreeNode *pNewElem = _pNodeFactory->create();
00891
00892 pNewElem->setNode (getActNode());
00893 pNewElem->setFunctor (func);
00894 pNewElem->setMatrixStore(_currMatrix);
00895 pNewElem->setLightsState(_lightsState);
00896 pNewElem->setClipPlanesState(_clipPlanesState);
00897 pNewElem->setState(pState);
00898 if(sortKey == Material::NoStateSorting)
00899 pNewElem->setNoStateSorting();
00900
00901 if(isMultiPass)
00902 {
00903 if(mpi == mpMatPasses-1)
00904 pNewElem->setLastMultiPass();
00905 else
00906 pNewElem->setMultiPass();
00907 }
00908
00909 if(!pMat->isTransparent())
00910 {
00911 if(_pNoStateSortRoot == NULL)
00912 _pNoStateSortRoot = pNewElem;
00913 else
00914 _pNoStateSortRoot->addChild(pNewElem);
00915 }
00916 else
00917 {
00918 if(_pNoStateSortTransRoot == NULL)
00919 _pNoStateSortTransRoot = pNewElem;
00920 else
00921 _pNoStateSortTransRoot->addChild(pNewElem);
00922 }
00923 }
00924
00925 return;
00926 }
00927
00928 MaterialMap::iterator it = _mMatMap.find(pMat);
00929
00930 #if 0
00931 pMat->rebuildState();
00932 #endif
00933
00934 if(sortKey == Material::NoStateSorting)
00935 sortKey = 0;
00936
00937 DrawTreeNode *pLastMultiPass = NULL;
00938
00939 if(_bSortTrans && pMat->isTransparent())
00940 {
00941 for(UInt32 mpi=0;mpi<mpMatPasses;++mpi)
00942 {
00943 pState = states[mpi];
00944
00945 DrawTreeNode *pNewElem = _pNodeFactory->create();
00946 Pnt3f objPos;
00947 getActNode()->getVolume().getCenter(objPos);
00948
00949 _currMatrix.second.mult(objPos);
00950
00951 pNewElem->setNode (getActNode());
00952
00953 pNewElem->setFunctor (func);
00954 pNewElem->setMatrixStore(_currMatrix);
00955
00956 pNewElem->setState (pState);
00957 pNewElem->setScalar (objPos[2]);
00958 pNewElem->setLightsState(_lightsState);
00959 pNewElem->setClipPlanesState(_clipPlanesState);
00960
00961 if(isMultiPass)
00962 {
00963 if(mpi == mpMatPasses-1)
00964 pNewElem->setLastMultiPass();
00965 else
00966 pNewElem->setMultiPass();
00967 }
00968
00969 if(_pTransMatRoots.find(sortKey) == _pTransMatRoots.end())
00970 {
00971 TransSortMap ts;
00972 _pTransMatRoots.insert(std::make_pair(sortKey, ts));
00973 }
00974
00975 TransSortMap &ts = _pTransMatRoots[sortKey];
00976 TransSortMap::iterator it = ts.find(pNewElem->getScalar());
00977 if(it == ts.end())
00978 ts.insert(std::make_pair(pNewElem->getScalar(), pNewElem));
00979 else
00980 (*it).second->addChild(pNewElem);
00981
00982 _uiNumTransGeometries++;
00983 }
00984 }
00985 else
00986 {
00987 if(it == _mMatMap.end())
00988 {
00989 DrawTreeNode *pNewMatElem = _pNodeFactory->create();
00990 _mMatMap[pMat] = pNewMatElem;
00991
00992 if(!isMultiPass)
00993 {
00994 pState = states[0];
00995
00996
00997 pNewMatElem->setState(pState);
00998 pNewMatElem->setNode(getActNode());
00999 pNewMatElem->setLightsState(_lightsState);
01000 pNewMatElem->setClipPlanesState(_clipPlanesState);
01001
01002 DrawTreeNode *pNewElem = _pNodeFactory->create();
01003 pNewElem->setNode (getActNode());
01004 pNewElem->setFunctor (func);
01005 pNewElem->setMatrixStore(_currMatrix);
01006 pNewElem->setLightsState(_lightsState);
01007 pNewElem->setClipPlanesState(_clipPlanesState);
01008
01009 pNewMatElem->addChild(pNewElem);
01010
01011 if(_pMatRoots.find(sortKey) == _pMatRoots.end())
01012 _pMatRoots.insert(std::make_pair(sortKey, _pNodeFactory->create()));
01013
01014 _pMatRoots[sortKey]->addChild(pNewMatElem);
01015 }
01016 else
01017 {
01018 pNewMatElem->setNode(getActNode());
01019 pNewMatElem->setLightsState(_lightsState);
01020 pNewMatElem->setClipPlanesState(_clipPlanesState);
01021
01022 for(UInt32 mpi=0;mpi<mpMatPasses;++mpi)
01023 {
01024 pState = states[mpi];
01025
01026 DrawTreeNode *pNewPassElem = _pNodeFactory->create();
01027 pNewPassElem->setState(pState);
01028 pNewPassElem->setNode(getActNode());
01029 pNewPassElem->setLightsState(_lightsState);
01030 pNewPassElem->setClipPlanesState(_clipPlanesState);
01031 pNewMatElem->addChild(pNewPassElem);
01032
01033 DrawTreeNode *pNewElem = _pNodeFactory->create();
01034 pNewElem->setNode (getActNode());
01035 pNewElem->setFunctor (func);
01036 pNewElem->setMatrixStore(_currMatrix);
01037 pNewElem->setLightsState(_lightsState);
01038 pNewElem->setClipPlanesState(_clipPlanesState);
01039
01040 if(isMultiPass)
01041 {
01042 if(mpi == mpMatPasses-1)
01043 pNewElem->setLastMultiPass();
01044 else
01045 pNewElem->setMultiPass();
01046 }
01047
01048 pNewPassElem->addChild(pNewElem);
01049 }
01050
01051 if(_pMatRoots.find(sortKey) == _pMatRoots.end())
01052 _pMatRoots.insert(std::make_pair(sortKey, _pNodeFactory->create()));
01053
01054 _pMatRoots[sortKey]->addChild(pNewMatElem);
01055 }
01056 }
01057 else
01058 {
01059 if(!isMultiPass)
01060 {
01061 DrawTreeNode *pNewElem = _pNodeFactory->create();
01062 pNewElem->setNode (getActNode());
01063 pNewElem->setFunctor (func);
01064 pNewElem->setMatrixStore(_currMatrix);
01065 pNewElem->setLightsState(_lightsState);
01066 pNewElem->setClipPlanesState(_clipPlanesState);
01067 it->second->addChild(pNewElem);
01068 }
01069 else
01070 {
01071
01072
01073
01074
01075
01076
01077
01078 DrawTreeNode *pNewPassElem = it->second->getFirstChild();
01079 for(UInt32 mpi=0;mpi<mpMatPasses;++mpi)
01080 {
01081 DrawTreeNode *pNewElem = _pNodeFactory->create();
01082 pNewElem->setNode (getActNode());
01083 pNewElem->setFunctor (func);
01084 pNewElem->setMatrixStore(_currMatrix);
01085 pNewElem->setLightsState(_lightsState);
01086 pNewElem->setClipPlanesState(_clipPlanesState);
01087
01088 if(isMultiPass)
01089 {
01090 if(mpi == mpMatPasses-1)
01091 pNewElem->setLastMultiPass();
01092 else
01093 pNewElem->setMultiPass();
01094 }
01095
01096 pNewPassElem->addChild(pNewElem);
01097 pNewPassElem = pNewPassElem->getBrother();
01098 }
01099 }
01100 }
01101 }
01102 }
01103
01104 void RenderAction::dropLight(Light *pLight)
01105 {
01106 if(pLight == NULL)
01107 return;
01108
01109 LightStore oStore;
01110
01111 pLight->makeChunk();
01112
01113 oStore.first = pLight->getChunk().getCPtr();
01114
01115
01116 Matrix fromworld,tobeacon;
01117
01118
01119
01120
01121
01122 NodePtr beacon = pLight->getBeacon();
01123
01124 if(beacon == NullFC)
01125 {
01126 SINFO << "draw: no beacon set!" << std::endl;
01127
01128 oStore.second = _currMatrix.second;
01129 }
01130 else
01131 {
01132 fromworld = _camInverse;
01133 fromworld.invert();
01134
01135 beacon->getToWorld(tobeacon);
01136
01137
01138
01139 fromworld.mult(tobeacon);
01140
01141 oStore.second = fromworld;
01142 }
01143
01144 if(!_bLocalLights && _vLights.size() >= 8)
01145 {
01146 SWARNING << "RenderAction::dropLight: maximum light source limit is " << 8
01147 << " skipping light sources!" << std::endl;
01148 }
01149
01150 _vLights.push_back(oStore);
01151 _lightsMap.push_back(pLight);
01152
01153 if(_bLocalLights)
01154 {
01155
01156 UInt32 lightState = _vLights.size();
01157 _lightsPath.push_back(lightState);
01158
01159 _lightsTable.push_back(_lightsPath);
01160 _lightsState = lightState;
01161 }
01162 }
01163
01164 void RenderAction::undropLight(Light *pLight)
01165 {
01166 if(pLight == NULL)
01167 return;
01168
01169 if(!_bLocalLights)
01170 return;
01171
01172 if(_lightEnvsLightsState.empty())
01173 {
01174 _lightsPath.pop_back();
01175 if(!_lightsPath.empty())
01176 _lightsState = _lightsPath.back();
01177 else
01178 _lightsState = 0;
01179 }
01180 }
01181
01182 void RenderAction::dropLightEnv(LightEnv *pLightEnv)
01183 {
01184 if(pLightEnv == NULL)
01185 return;
01186
01187 if(!_bLocalLights)
01188 return;
01189
01190 _lightEnvsLightsState.push_back(_lightsState);
01191 }
01192
01193 void RenderAction::undropLightEnv(LightEnv *pLightEnv)
01194 {
01195 if(pLightEnv == NULL)
01196 return;
01197
01198 if(!_bLocalLights)
01199 return;
01200
01201 _lightsState = _lightEnvsLightsState.back();
01202 if(_lightsState > 0)
01203 _lightsPath = _lightsTable[_lightsState - 1];
01204 else
01205 _lightsPath.clear();
01206 _lightEnvsLightsState.pop_back();
01207 }
01208
01209 std::vector<Light *> RenderAction::getActiveLights(void)
01210 {
01211 std::vector<Light *> lights;
01212 if(_bLocalLights)
01213 {
01214 if(_activeLightsState > 0)
01215 {
01216 const std::vector<UInt32> &light_ids = _lightsTable[_activeLightsState - 1];
01217
01218 for(UInt32 i=0;i<light_ids.size();++i)
01219 {
01220 UInt32 light_id = light_ids[i];
01221 if(light_id > 0 && light_id <= _lightsMap.size())
01222 lights.push_back(_lightsMap[light_id - 1]);
01223 }
01224 }
01225 }
01226 else
01227 {
01228 return _lightsMap;
01229 }
01230 return lights;
01231 }
01232
01233 void RenderAction::dropClipPlane(ClipPlane *pClipPlane)
01234 {
01235 if(pClipPlane == NULL)
01236 return;
01237
01238 ClipPlaneStore oStore;
01239
01240 pClipPlane->makeChunk();
01241
01242 oStore.first = pClipPlane->getChunk().getCPtr();
01243
01244
01245 Matrix fromworld,tobeacon;
01246
01247
01248
01249
01250
01251 NodePtr beacon = pClipPlane->getBeacon();
01252
01253 if(beacon == NullFC)
01254 {
01255 SINFO << "draw: no beacon set!" << std::endl;
01256
01257 oStore.second = _currMatrix.second;
01258 }
01259 else
01260 {
01261 fromworld = _camInverse;
01262 fromworld.invert();
01263
01264 beacon->getToWorld(tobeacon);
01265
01266
01267
01268 fromworld.mult(tobeacon);
01269
01270 oStore.second = fromworld;
01271 }
01272
01273 _vClipPlanes.push_back(oStore);
01274 _clipPlanesMap.push_back(pClipPlane);
01275
01276
01277 UInt32 clipPlaneState = _vClipPlanes.size();
01278 _clipPlanesPath.push_back(clipPlaneState);
01279
01280 _clipPlanesTable.push_back(_clipPlanesPath);
01281 _clipPlanesState = clipPlaneState;
01282 }
01283
01284 void RenderAction::undropClipPlane(ClipPlane *pClipPlane)
01285 {
01286 if(pClipPlane == NULL)
01287 return;
01288
01289 _clipPlanesPath.pop_back();
01290 if(!_clipPlanesPath.empty())
01291 _clipPlanesState = _clipPlanesPath.back();
01292 else
01293 _clipPlanesState = 0;
01294 }
01295
01296 bool RenderAction::isVisible( Node* node )
01297 {
01298 if ( getFrustumCulling() == false )
01299 return true;
01300
01301
01302
01303 if(!_lightEnvsLightsState.empty())
01304 return true;
01305
01306 getStatistics()->getElem(statCullTestedNodes)->inc();
01307
01308 DynamicVolume vol;
01309
01310
01311
01312 node->updateVolume();
01313 vol = node->getVolume();
01314
01315 vol.transform(top_matrix());
01316
01317 if ( _frustum.intersect( vol ) )
01318 {
01319
01320 return true;
01321 }
01322
01323 getStatistics()->getElem(statCulledNodes)->inc();
01324
01325
01326
01327 return false;
01328 }
01329
01331
01332
01333 bool RenderAction::pushVisibility(void)
01334 {
01335 if(getFrustumCulling() == false)
01336 return true;
01337
01338
01339
01340 if(!_lightEnvsLightsState.empty())
01341 return true;
01342
01343 FrustumVolume::PlaneSet inplanes = _visibilityStack.back();
01344
01345 if(inplanes == FrustumVolume::P_ALL)
01346 {
01347 _visibilityStack.push_back(inplanes);
01348 return true;
01349 }
01350
01351 Color3f col;
01352 bool result = true;
01353
01354 NodePtr node = getActNode();
01355
01356 DynamicVolume vol = node->getVolume(true);
01357 FrustumVolume frustum = _frustum;
01358
01359 #if 1
01360 vol.transform(top_matrix());
01361 #else
01362
01363 Matrix m = top_matrix();
01364 m.invert();
01365
01366 frustum.transform(m);
01367 #endif
01368
01369 getStatistics()->getElem(statCullTestedNodes)->inc();
01370
01371 if ( !intersect( frustum, vol, inplanes ) )
01372 {
01373 result = false;
01374 col.setValuesRGB(1,0,0);
01375 getStatistics()->getElem(statCulledNodes)->inc();
01376 useNodeList();
01377 }
01378 else
01379 {
01380 if(inplanes == FrustumVolume::P_ALL)
01381 {
01382 col.setValuesRGB(0,1,0);
01383 }
01384 else
01385 {
01386 col.setValuesRGB(0,0,1);
01387 }
01388 }
01389
01390 if(getVolumeDrawing())
01391 {
01392 dropVolume(this, node, col);
01393 }
01394
01395 _visibilityStack.push_back(inplanes);
01396 return result;
01397 }
01398
01399 void RenderAction::popVisibility(void)
01400 {
01401 if(getFrustumCulling() == false)
01402 return;
01403
01404 if(!_lightEnvsLightsState.empty())
01405 return;
01406
01407 if(!_visibilityStack.empty())
01408 _visibilityStack.pop_back();
01409 else
01410 SWARNING << "RenderAction::popVisibility: visibility stack is empty looks"
01411 "like a pushVisibility and popVisibility mismatch!" << std::endl;
01412 }
01413
01414
01415
01416
01417 void RenderAction::dump(DrawTreeNode *pRoot, UInt32 uiIndent)
01418 {
01419 if(pRoot == NULL)
01420 {
01421 return;
01422 }
01423
01424 indentLog(uiIndent, PWARNING);
01425
01426 PWARNING << "Node : " << pRoot << " | "
01427 << "Geo : " << pRoot->getGeometry() << " | "
01428 << "State : " << pRoot->getState() << " | "
01429 << "Node : " << pRoot->getNode() << " | "
01430 << "Matrix : " << pRoot->getMatrixStore().first << std::endl;
01431
01432 indentLog(uiIndent, PWARNING);
01433 PWARNING << "{" << std::endl;
01434
01435 if(pRoot->getFirstChild() != NULL)
01436 {
01437 dump(pRoot->getFirstChild(), uiIndent + 4);
01438 }
01439
01440 indentLog(uiIndent, PWARNING);
01441 PWARNING << "}" << std::endl;
01442
01443 if(pRoot->getBrother() != NULL)
01444 {
01445 dump(pRoot->getBrother(), uiIndent);
01446 }
01447 }
01448
01449 void RenderAction::activateLocalLights(DrawTreeNode *pRoot)
01450 {
01451
01452 if(_activeLightsState == pRoot->getLightsState())
01453 return;
01454
01455 UInt32 light_id = 0;
01456 if(pRoot->getLightsState() > 0)
01457 {
01458 _activeLightsMask = 0;
01459 const std::vector<UInt32> &lights = _lightsTable[pRoot->getLightsState() - 1];
01460
01461
01462 for(UInt32 i=0;i<lights.size();++i)
01463 {
01464 UInt32 light_index = lights[i] - 1;
01465 glPushMatrix();
01466 glLoadMatrixf(_vLights[light_index].second.getValues());
01467 _activeLightsMask |= (1 << light_id);
01468
01469 _vLights[light_index].first->activate(this, light_id++);
01470 glPopMatrix();
01471 ++_uiNumLightChanges;
01472 }
01473
01474 }
01475
01476 if(light_id > 8)
01477 {
01478 SWARNING << "RenderAction::activateLocalLights: maximum light source limit is " << 8
01479 << std::endl;
01480 }
01481
01482
01483 const Color4f black(0.0f, 0.0f, 0.0f, 1.0f);
01484 for(UInt32 i = light_id;i < _activeLightsCount;++i)
01485 {
01486
01487 _activeLightsMask &= ~(1 << i);
01488
01489 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE,
01490 black.getValuesRGBA());
01491 glDisable(GL_LIGHT0 + i);
01492 ++_uiNumLightChanges;
01493 }
01494
01495
01496 _activeLightsState = pRoot->getLightsState();
01497 _activeLightsCount = light_id;
01498 }
01499
01500 void RenderAction::activateLocalClipPlanes(DrawTreeNode *pRoot)
01501 {
01502
01503 if(_activeClipPlanesState == pRoot->getClipPlanesState())
01504 return;
01505
01506 UInt32 clipPlane_id = 0;
01507 if(pRoot->getClipPlanesState() > 0)
01508 {
01509 _activeClipPlanesMask = 0;
01510 const std::vector<UInt32> &clipPlanes = _clipPlanesTable[pRoot->getClipPlanesState() - 1];
01511
01512
01513 for(UInt32 i=0;i<clipPlanes.size();++i)
01514 {
01515 UInt32 clipPlane_index = clipPlanes[i] - 1;
01516 glPushMatrix();
01517 glLoadMatrixf(_vClipPlanes[clipPlane_index].second.getValues());
01518 _activeClipPlanesMask |= (1 << clipPlane_id);
01519
01520 _vClipPlanes[clipPlane_index].first->activate(this, clipPlane_id++);
01521 glPopMatrix();
01522 }
01523
01524 }
01525
01526 if(clipPlane_id > 6)
01527 {
01528 SWARNING << "RenderAction::activateLocalClipPlanes: maximum clipping planes limit is " << 6
01529 << std::endl;
01530 }
01531
01532
01533 const Color4f black(0.0f, 0.0f, 0.0f, 1.0f);
01534 for(UInt32 i = clipPlane_id;i < _activeClipPlanesCount;++i)
01535 {
01536
01537 _activeClipPlanesMask &= ~(1 << i);
01538 glDisable(GL_CLIP_PLANE0 + i);
01539 }
01540
01541
01542 _activeClipPlanesState = pRoot->getClipPlanesState();
01543 _activeClipPlanesCount = clipPlane_id;
01544 }
01545
01546 bool RenderAction::isSmallFeature(const NodePtr &node)
01547 {
01548 if(node == NullFC)
01549 return true;
01550
01551 if(!_bSmallFeatureCulling)
01552 return false;
01553
01554
01555 DynamicVolume vol = node->getVolume();
01556 vol.transform(top_matrix());
01557
01558 Pnt3f p[8];
01559 vol.getBounds(p[0], p[4]);
01560
01561 p[1].setValues(p[0][0], p[4][1], p[0][2]);
01562 p[2].setValues(p[4][0], p[4][1], p[0][2]);
01563 p[3].setValues(p[4][0], p[0][1], p[0][2]);
01564
01565 p[5].setValues(p[4][0], p[0][1], p[4][2]);
01566 p[6].setValues(p[0][0], p[0][1], p[4][2]);
01567 p[7].setValues(p[0][0], p[4][1], p[4][2]);
01568
01569 for(int i=0;i<8;++i)
01570 _worldToScreenMatrix.multFullMatrixPnt(p[i]);
01571
01572 Pnt2f min(OSG::Inf, OSG::Inf);
01573 Pnt2f max(OSG::NegInf, OSG::NegInf);
01574
01575 for(int i=0;i<8;++i)
01576 {
01577 if(p[i][0] < min[0])
01578 min[0] = p[i][0];
01579
01580 if(p[i][1] < min[1])
01581 min[1] = p[i][1];
01582
01583 if(p[i][0] > max[0])
01584 max[0] = p[i][0];
01585
01586 if(p[i][1] > max[1])
01587 max[1] = p[i][1];
01588 }
01589
01590
01591
01592
01593 Real32 w = ((max[0] - min[0]) / 2.0f) * Real32(_viewport->getPixelWidth());
01594 Real32 h = ((max[1] - min[1]) / 2.0f) * Real32(_viewport->getPixelHeight());
01595 Real32 f = w * h;
01596
01597
01598
01599 if(f <= _smallFeaturesPixels)
01600 return true;
01601
01602 return false;
01603 }
01604
01605 bool RenderAction::isOccluded(DrawTreeNode *pRoot)
01606 {
01607
01608 if(!pRoot->hasFunctor())
01609 return false;
01610
01611
01612 UInt32 pos_size = 0;
01613 if((_bOcclusionCulling || _bSmallFeatureCulling) &&
01614 pRoot->getNode()->getCore() != NullFC)
01615 {
01616 GeometryPtr geo = GeometryPtr::dcast(pRoot->getNode()->getCore());
01617 if(geo != NullFC)
01618 {
01619 if(geo->getPositions() != NullFC)
01620 pos_size = geo->getPositions()->getSize();
01621 }
01622 }
01623
01624 bool foundSmallFeature = false;
01625 if(_bSmallFeatureCulling && pos_size > _smallFeaturesThreshold)
01626 {
01627 foundSmallFeature = isSmallFeature(pRoot->getNode());
01628 if(foundSmallFeature)
01629 {
01630 getStatistics()->getElem(statCulledNodes)->inc();
01631 return true;
01632 }
01633 }
01634
01635 if(!foundSmallFeature)
01636 {
01637 if(_bOcclusionCulling && _glGenQueriesARB != NULL &&
01638 ((pos_size > _occlusionCullingThreshold) ||
01639 (_occlusionCullingMode == OcclusionHierarchicalMultiFrame)))
01640 {
01641 if(_occlusionCullingMode & OcclusionMultiFrame)
01642 {
01643
01644
01645
01646
01647
01648
01649 GLuint occlusionQuery = getOcclusionQuery(pRoot->getNode());
01650 if(occlusionQuery == 0)
01651 return false;
01652
01653 GLuint pixels = 0;
01654 _glGetQueryObjectuivARB(occlusionQuery, GL_QUERY_RESULT_ARB, &pixels);
01655 ++_uiNumOcclusionTests;
01656
01657
01658 if(pixels > _occlusionCullingPixels)
01659 {
01660
01661 pRoot->getNode()->setOcclusionMask(0);
01662 return false;
01663 }
01664 else
01665 {
01666
01667 pRoot->getNode()->setOcclusionMask(2);
01668 _occluded_nodes.push_back(pRoot->getNode());
01669 getStatistics()->getElem(statCulledNodes)->inc();
01670 ++_uiNumOcclusionCulled;
01671 return true;
01672 }
01673 }
01674 else if(_occlusionCullingMode & OcclusionStopAndWait)
01675 {
01676
01677
01678
01679
01680
01681
01682
01683 glDepthMask(GL_FALSE);
01684 glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);
01685
01686 if(_occlusionQuery == 0)
01687 _glGenQueriesARB(1, &_occlusionQuery);
01688
01689 const DynamicVolume& vol = pRoot->getNode()->getVolume();
01690 Pnt3f min,max;
01691 vol.getBounds(min, max);
01692
01693 _glBeginQueryARB(GL_SAMPLES_PASSED_ARB, _occlusionQuery);
01694 drawOcclusionBB(min, max);
01695 _glEndQueryARB(GL_SAMPLES_PASSED_ARB);
01696
01697 glDepthMask(GL_TRUE);
01698 glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
01699
01700 GLuint pixels = 0;
01701 _glGetQueryObjectuivARB(_occlusionQuery, GL_QUERY_RESULT_ARB, &pixels);
01702 ++_uiNumOcclusionTests;
01703
01704 if(pixels > _occlusionCullingPixels)
01705 {
01706 return false;
01707 }
01708 else
01709 {
01710 getStatistics()->getElem(statCulledNodes)->inc();
01711 ++_uiNumOcclusionCulled;
01712 return true;
01713 }
01714 }
01715 }
01716 }
01717
01718 return false;
01719 }
01720
01721 void RenderAction::deleteOcclusionQueriesPool(void)
01722 {
01723 for(std::vector<GLuint>::iterator occIt = _occlusionQueriesPool.begin();
01724 occIt != _occlusionQueriesPool.end();++occIt)
01725 {
01726 GLuint occlusionQuery = (*occIt);
01727 _glDeleteQueriesARB(1, &occlusionQuery);
01728 }
01729 _occlusionQueriesPool.clear();
01730
01731 for(std::map<UInt32, GLuint>::iterator it=_occlusionQueries.begin();
01732 it!=_occlusionQueries.end();++it)
01733 {
01734 NodePtr node = NodePtr::dcast(FieldContainerFactory::the()->getContainer((*it).first));
01735 if(node != NullFC)
01736 setOcclusionMask(node, 0);
01737 }
01738 _occlusionQueries.clear();
01739 _occluded_nodes.clear();
01740
01741 for(std::set<UInt32>::iterator it=_hier_occlusions.begin();
01742 it!=_hier_occlusions.end();++it)
01743 {
01744 NodePtr node = NodePtr::dcast(FieldContainerFactory::the()->getContainer(*it));
01745 if(node != NullFC)
01746 setOcclusionMask(node, 0);
01747 }
01748 _hier_occlusions.clear();
01749
01750 #if 0
01751
01752 Viewport *vp = getViewport();
01753 if(vp != NULL)
01754 {
01755 NodePtr root = vp->getRoot();
01756 setOcclusionMask(root, 0);
01757 }
01758 #endif
01759 }
01760
01761 void RenderAction::resetOcclusionQueryIndex(void)
01762 {
01763 _currentOcclusionQueryIndex = 0;
01764 }
01765
01766 void RenderAction::setOcclusionMask(NodePtr node, UInt8 mask)
01767 {
01768 if(node == NullFC)
01769 return;
01770
01771 node->setOcclusionMask(mask);
01772
01773 for(UInt32 i=0;i<node->getNChildren();++i)
01774 setOcclusionMask(node->getChild(i), mask);
01775 }
01776
01777 bool RenderAction::hasGeometryChild(NodePtr node)
01778 {
01779 if(node == NullFC)
01780 return false;
01781
01782 if(GeometryPtr::dcast(node->getCore()) != NullFC)
01783 return true;
01784
01785 for(UInt32 i=0;i<node->getNChildren();++i)
01786 {
01787 if(hasGeometryChild(node->getChild(i)))
01788 return true;
01789 }
01790
01791 return false;
01792 }
01793
01794 GLuint RenderAction::getOcclusionQuery(void)
01795 {
01796 GLuint occlusionQuery = 0;
01797 if(_currentOcclusionQueryIndex >= _occlusionQueriesPool.size())
01798 {
01799
01800 _glGenQueriesARB(1, &occlusionQuery);
01801 _occlusionQueriesPool.push_back(occlusionQuery);
01802 }
01803 else
01804 {
01805 occlusionQuery = _occlusionQueriesPool[_currentOcclusionQueryIndex];
01806 }
01807
01808 ++_currentOcclusionQueryIndex;
01809
01810 return occlusionQuery;
01811 }
01812
01813 GLuint RenderAction::getOcclusionQuery(NodePtr node)
01814 {
01815 if(node == NullFC)
01816 return 0;
01817
01818 std::map<UInt32, GLuint>::iterator it = _occlusionQueries.find(node.getFieldContainerId());
01819
01820 if(it != _occlusionQueries.end())
01821 return (*it).second;
01822
01823 return 0;
01824 }
01825
01826 void RenderAction::setOcclusionQuery(NodePtr node, GLuint occlusionQuery)
01827 {
01828 if(node == NullFC)
01829 return;
01830
01831 _occlusionQueries.insert(std::make_pair(node.getFieldContainerId(), occlusionQuery));
01832 }
01833
01834 void RenderAction::drawOcclusionBB(const Pnt3f &bbmin, const Pnt3f &bbmax)
01835 {
01836 #if 1
01837
01838 #if 0
01839 glBegin(GL_TRIANGLE_STRIP);
01840 glVertex3f( bbmin[0], bbmin[1], bbmax[2]);
01841 glVertex3f( bbmax[0], bbmin[1], bbmax[2]);
01842 glVertex3f( bbmin[0], bbmax[1], bbmax[2]);
01843 glVertex3f( bbmax[0], bbmax[1], bbmax[2]);
01844 glVertex3f( bbmin[0], bbmax[1], bbmin[2]);
01845 glVertex3f( bbmax[0], bbmax[1], bbmin[2]);
01846 glVertex3f( bbmin[0], bbmin[1], bbmin[2]);
01847 glVertex3f( bbmax[0], bbmin[1], bbmin[2]);
01848 glEnd();
01849
01850 glBegin(GL_TRIANGLE_STRIP);
01851 glVertex3f( bbmax[0], bbmax[1], bbmin[2]);
01852 glVertex3f( bbmax[0], bbmax[1], bbmax[2]);
01853 glVertex3f( bbmax[0], bbmin[1], bbmin[2]);
01854 glVertex3f( bbmax[0], bbmin[1], bbmax[2]);
01855 glVertex3f( bbmin[0], bbmin[1], bbmin[2]);
01856 glVertex3f( bbmin[0], bbmin[1], bbmax[2]);
01857 glVertex3f( bbmin[0], bbmax[1], bbmin[2]);
01858 glVertex3f( bbmin[0], bbmax[1], bbmax[2]);
01859 glEnd();
01860
01861 #else
01862
01863
01864
01865 const GLubyte indices[16] = { 0,1,2,3,4,5,6,7, 5,3,7,1,6,0,4,2 };
01866 Real32 vertices[24];
01867 vertices[0] = bbmin[0]; vertices[1] = bbmin[1]; vertices[2] = bbmax[2];
01868 vertices[3] = bbmax[0]; vertices[4] = bbmin[1]; vertices[5] = bbmax[2];
01869 vertices[6] = bbmin[0]; vertices[7] = bbmax[1]; vertices[8] = bbmax[2];
01870 vertices[9] = bbmax[0]; vertices[10] = bbmax[1]; vertices[11] = bbmax[2];
01871 vertices[12] = bbmin[0]; vertices[13] = bbmax[1]; vertices[14] = bbmin[2];
01872 vertices[15] = bbmax[0]; vertices[16] = bbmax[1]; vertices[17] = bbmin[2];
01873 vertices[18] = bbmin[0]; vertices[19] = bbmin[1]; vertices[20] = bbmin[2];
01874 vertices[21] = bbmax[0]; vertices[22] = bbmin[1]; vertices[23] = bbmin[2];
01875
01876 glVertexPointer(3, GL_FLOAT, 0, &vertices[0]);
01877 glEnableClientState(GL_VERTEX_ARRAY);
01878 glDrawElements(GL_TRIANGLE_STRIP, 8, GL_UNSIGNED_BYTE, &indices[0]);
01879 glDrawElements(GL_TRIANGLE_STRIP, 8, GL_UNSIGNED_BYTE, &indices[8]);
01880 glDisableClientState(GL_VERTEX_ARRAY);
01881
01882 #endif
01883
01884 #else
01885
01886 if(_occ_bb_dl == 0)
01887 {
01888
01889
01890
01891 Pnt3f min(-0.5f, -0.5f, -0.5f);
01892 Pnt3f max(0.5f, 0.5f, 0.5f);
01893 _occ_bb_dl = glGenLists(1);
01894
01895 const GLubyte indices[16] = { 0,1,2,3,4,5,6,7, 5,3,7,1,6,0,4,2 };
01896 Real32 vertices[24];
01897 vertices[0] = min[0]; vertices[1] = min[1]; vertices[2] = max[2];
01898 vertices[3] = max[0]; vertices[4] = min[1]; vertices[5] = max[2];
01899 vertices[6] = min[0]; vertices[7] = max[1]; vertices[8] = max[2];
01900 vertices[9] = max[0]; vertices[10] = max[1]; vertices[11] = max[2];
01901 vertices[12] = min[0]; vertices[13] = max[1]; vertices[14] = min[2];
01902 vertices[15] = max[0]; vertices[16] = max[1]; vertices[17] = min[2];
01903 vertices[18] = min[0]; vertices[19] = min[1]; vertices[20] = min[2];
01904 vertices[21] = max[0]; vertices[22] = min[1]; vertices[23] = min[2];
01905
01906 glNewList(_occ_bb_dl, GL_COMPILE);
01907 glVertexPointer(3, GL_FLOAT, 0, &vertices[0]);
01908 glEnableClientState(GL_VERTEX_ARRAY);
01909 glDrawElements(GL_TRIANGLE_STRIP, 8, GL_UNSIGNED_BYTE, &indices[0]);
01910 glDrawElements(GL_TRIANGLE_STRIP, 8, GL_UNSIGNED_BYTE, &indices[8]);
01911 glDisableClientState(GL_VERTEX_ARRAY);
01912 glEndList();
01913 }
01914
01915 Vec3f s = bbmax - bbmin;
01916 Vec3f t = bbmin + bbmax;
01917 t *= 0.5f;
01918 glPushMatrix();
01919 glTranslatef(t[0], t[1], t[2]);
01920 glScalef(s[0], s[1], s[2]);
01921 glCallList(_occ_bb_dl);
01922 glPopMatrix();
01923
01924 #endif
01925 }
01926
01927 void RenderAction::drawMultiFrameOcclusionBB(DrawTreeNode *pRoot)
01928 {
01929 while(pRoot != NULL)
01930 {
01931 if(pRoot->hasFunctor())
01932 {
01933 UInt32 pos_size = 0;
01934 GeometryPtr geo = GeometryPtr::dcast(pRoot->getNode()->getCore());
01935 if(geo != NullFC)
01936 {
01937 if(geo->getPositions() != NullFC)
01938 pos_size = geo->getPositions()->getSize();
01939 }
01940
01941 if(_glGenQueriesARB != NULL && ((pos_size > _occlusionCullingThreshold) ||
01942 (_occlusionCullingMode == OcclusionHierarchicalMultiFrame)))
01943 {
01944 DynamicVolume vol = pRoot->getNode()->getVolume();
01945 vol.transform(pRoot->getMatrixStore().second);
01946
01947 if(vol.getMax()[2] < 0.0f)
01948 {
01949 UInt32 uiNextMatrix = pRoot->getMatrixStore().first;
01950 if(uiNextMatrix != 0 && uiNextMatrix != _uiActiveMatrix)
01951 {
01952 glLoadMatrixf(pRoot->getMatrixStore().second.getValues());
01953
01954 _uiActiveMatrix = uiNextMatrix;
01955 _uiNumMatrixChanges++;
01956 _currMatrix.second = pRoot->getMatrixStore().second;
01957 }
01958
01959 Pnt3f min,max;
01960 pRoot->getNode()->getVolume().getBounds(min, max);
01961
01962 GLuint occlusionQuery = getOcclusionQuery();
01963
01964 _glBeginQueryARB(GL_SAMPLES_PASSED_ARB, occlusionQuery);
01965 drawOcclusionBB(min, max);
01966 _glEndQueryARB(GL_SAMPLES_PASSED_ARB);
01967
01968
01969 setOcclusionQuery(pRoot->getNode(), occlusionQuery);
01970 }
01971 else
01972 {
01973 setOcclusionQuery(pRoot->getNode(), 0);
01974 }
01975 }
01976 }
01977
01978 if(pRoot->getFirstChild() != NULL)
01979 {
01980 drawMultiFrameOcclusionBB(pRoot->getFirstChild());
01981 }
01982
01983 pRoot = pRoot->getBrother();
01984 }
01985 }
01986
01987 void RenderAction::drawHierarchicalMultiFrameOcclusionBB(const Matrix &view,
01988 NodePtr node)
01989 {
01990 if(node == NullFC || _glGenQueriesARB == NULL)
01991 return;
01992
01993 DynamicVolume vol = node->getVolume();
01994 Matrix m = view;
01995 if(node->getParent() != NullFC)
01996 m.mult(node->getParent()->getToWorld());
01997 vol.transform(m);
01998
01999 if(vol.getMax()[2] < 0.0f)
02000 {
02001 glLoadMatrixf(m.getValues());
02002 Pnt3f min,max;
02003 node->getVolume().getBounds(min, max);
02004
02005 GLuint occlusionQuery = getOcclusionQuery();
02006
02007 _glBeginQueryARB(GL_SAMPLES_PASSED_ARB, occlusionQuery);
02008 drawOcclusionBB(min, max);
02009 _glEndQueryARB(GL_SAMPLES_PASSED_ARB);
02010
02011
02012 setOcclusionQuery(node, occlusionQuery);
02013 }
02014 else
02015 {
02016 setOcclusionQuery(node, 0);
02017 }
02018 }
02019
02020
02021
02022 void RenderAction::updateShader(State *state)
02023 {
02024 if(state == NULL)
02025 return;
02026
02027 if(_cgChunkId != -1)
02028 {
02029 StateChunkPtr cgChunk = state->getChunk(_cgChunkId);
02030 if(cgChunk != NULL)
02031 cgChunk->update(this);
02032 }
02033
02034 if(_cgfxChunkId != -1)
02035 {
02036 StateChunkPtr cgfxChunk = state->getChunk(_cgfxChunkId);
02037 if(cgfxChunk != NULL)
02038 cgfxChunk->update(this);
02039 }
02040
02041 StateChunkPtr shlChunk = state->getChunk(_shlChunkId);
02042 if(shlChunk != NULL)
02043 shlChunk->update(this);
02044 }
02045
02046 void RenderAction::draw(DrawTreeNode *pRoot)
02047 {
02048 while(pRoot != NULL)
02049 {
02050 UInt32 uiNextMatrix = pRoot->getMatrixStore().first;
02051
02052 if(uiNextMatrix != 0 && uiNextMatrix != _uiActiveMatrix)
02053 {
02054 glLoadMatrixf(pRoot->getMatrixStore().second.getValues());
02055
02056 _uiActiveMatrix = uiNextMatrix;
02057
02058 _uiNumMatrixChanges++;
02059
02060 _currMatrix.second = pRoot->getMatrixStore().second;
02061 updateTopMatrix();
02062
02063
02064
02065
02066 if(_bCorrectTwoSidedLighting)
02067 {
02068 const Matrix &m = _currMatrix.second;
02069
02070
02071 if(m[0].cross(m[1]).dot(m[2]) < 0.0)
02072 glFrontFace(GL_CW);
02073 else
02074 glFrontFace(GL_CCW);
02075 }
02076
02077 #ifdef PRINT_MAT
02078 fprintf(stderr, "pushed to gl %d\n", _uiActiveMatrix);
02079
02080 for(int i = 0; i < 4; i++)
02081 {
02082 fprintf(stderr, "% 5.2f % 5.2f % 5.2f % 5.2f\n",
02083 pRoot->getMatrixStore().second[i][0],
02084 pRoot->getMatrixStore().second[i][1],
02085 pRoot->getMatrixStore().second[i][2],
02086 pRoot->getMatrixStore().second[i][3]);
02087 }
02088 #endif
02089 }
02090
02091 setActNode(pRoot->getNode());
02092
02093 if(!isOccluded(pRoot))
02094 {
02095 if(_bLocalLights && _activeLightsState != pRoot->getLightsState())
02096 activateLocalLights(pRoot);
02097
02098 activateLocalClipPlanes(pRoot);
02099
02100 State *pNewState = pRoot->getState();
02101
02102 if(pNewState != NULL)
02103 {
02104 if(_pActiveState != NULL)
02105 {
02106
02107
02108 if(pNewState != _pActiveState ||
02109 (_cgfxChunkId != -1 && pNewState->getChunk(_cgfxChunkId) != NULL) ||
02110 pRoot->isNoStateSorting())
02111 {
02112 State *previous_state = _pActiveState;
02113 _pActiveState = pNewState;
02114 pNewState->changeFrom(this, previous_state);
02115 _uiNumMaterialChanges++;
02116 }
02117 else
02118 {
02119
02120
02121 updateShader(pNewState);
02122 }
02123 }
02124 else
02125 {
02126 _pActiveState = pRoot->getState();
02127 _pActiveState->activate(this);
02128 _uiNumMaterialChanges++;
02129 }
02130 }
02131 else
02132 {
02133 updateShader(_pActiveState);
02134 }
02135
02136 if(pRoot->getGeometry() != NULL)
02137 {
02138 pRoot->getGeometry()->drawPrimitives(this);
02139 _uiNumGeometries++;
02140 }
02141 else if(pRoot->hasFunctor())
02142 {
02143 pRoot->getFunctor().call(this);
02144 _uiNumGeometries++;
02145 }
02146
02147 if(pNewState != NULL && pRoot->isLastMultiPass())
02148 {
02149
02150
02151
02152 _pActiveState = NULL;
02153
02154 pNewState->deactivate(this);
02155 _uiNumMaterialChanges++;
02156 }
02157 }
02158
02159 if(pRoot->getFirstChild() != NULL)
02160 {
02161 draw(pRoot->getFirstChild());
02162 }
02163
02164 pRoot = pRoot->getBrother();
02165 }
02166 }
02167
02168 void RenderAction::setSortTrans(bool bVal)
02169 {
02170 _bSortTrans = bVal;
02171 }
02172
02173 bool RenderAction::getSortTrans(void) const
02174 {
02175 return _bSortTrans;
02176 }
02177
02178 void RenderAction::setZWriteTrans(bool bVal)
02179 {
02180 _bZWriteTrans = bVal;
02181 }
02182
02183 bool RenderAction::getZWriteTrans(void) const
02184 {
02185 return _bZWriteTrans;
02186 }
02187
02188 void RenderAction::setLocalLights(bool bVal)
02189 {
02190 _bLocalLights = bVal;
02191 }
02192
02193 bool RenderAction::getLocalLights(void) const
02194 {
02195 return _bLocalLights;
02196 }
02197
02198 void RenderAction::setCorrectTwoSidedLighting(bool bVal)
02199 {
02200 _bCorrectTwoSidedLighting = bVal;
02201 }
02202
02203 bool RenderAction::getCorrectTwoSidedLighting(void) const
02204 {
02205 return _bCorrectTwoSidedLighting;
02206 }
02207
02208 void RenderAction::setOcclusionCulling(bool bVal)
02209 {
02210 if(_bOcclusionCulling == bVal)
02211 return;
02212
02213 deleteOcclusionQueriesPool();
02214 _bOcclusionCulling = bVal;
02215 }
02216
02217 bool RenderAction::getOcclusionCulling(void) const
02218 {
02219 return _bOcclusionCulling;
02220 }
02221
02222 void RenderAction::setOcclusionCullingMode(Int32 mode)
02223 {
02224 if(_occlusionCullingMode == mode)
02225 return;
02226
02227 deleteOcclusionQueriesPool();
02228 _occlusionCullingMode = mode;
02229 }
02230
02231 Int32 RenderAction::getOcclusionCullingMode(void) const
02232 {
02233 return _occlusionCullingMode;
02234 }
02235
02236 void RenderAction::setOcclusionCullingPixels(UInt32 pixels)
02237 {
02238 _occlusionCullingPixels = pixels;
02239 }
02240
02241 UInt32 RenderAction::getOcclusionCullingPixels(void) const
02242 {
02243 return _occlusionCullingPixels;
02244 }
02245
02246 void RenderAction::setSmallFeatureCulling(bool bVal)
02247 {
02248 _bSmallFeatureCulling = bVal;
02249 }
02250
02251 bool RenderAction::getSmallFeatureCulling(void) const
02252 {
02253 return _bSmallFeatureCulling;
02254 }
02255
02256 void RenderAction::setSmallFeaturePixels(Real32 pixels)
02257 {
02258 _smallFeaturesPixels = pixels;
02259 }
02260
02261 Real32 RenderAction::getSmallFeaturePixels(void) const
02262 {
02263 return _smallFeaturesPixels;
02264 }
02265
02266 void RenderAction::setSmallFeatureThreshold(UInt32 threshold)
02267 {
02268 _smallFeaturesThreshold = threshold;
02269 }
02270
02271 UInt32 RenderAction::getSmallFeatureThreshold(void) const
02272 {
02273 return _smallFeaturesThreshold;
02274 }
02275
02276 void RenderAction::setOcclusionCullingThreshold(UInt32 threshold)
02277 {
02278 _occlusionCullingThreshold = threshold;
02279 }
02280
02281 UInt32 RenderAction::getOcclusionCullingThreshold(void) const
02282 {
02283 return _occlusionCullingThreshold;
02284 }
02285
02286 void RenderAction::setUseGLFinish(bool s)
02287 {
02288 _useGLFinish = s;
02289 }
02290
02291 bool RenderAction::getUseGLFinish(void) const
02292 {
02293 return _useGLFinish;
02294 }
02295
02296
02297
02298
02299 Action::ResultE RenderAction::start(void)
02300 {
02301 glErr("RenderAction: precheck");
02302
02303 Inherited::start();
02304
02305 if(_window != NULL)
02306 {
02307 _window->resizeGL();
02308 }
02309
02310 if(_glGenQueriesARB == NULL &&
02311 _window->hasExtension(_arbOcclusionQuery))
02312 {
02313 _glGenQueriesARB = (void (OSG_APIENTRY*)(GLsizei, GLuint *)) _window->getFunction(_funcGenQueriesARB);
02314 _glDeleteQueriesARB = (void (OSG_APIENTRY*)(GLsizei, GLuint *)) _window->getFunction(_funcDeleteQueriesARB);
02315 _glBeginQueryARB = (void (OSG_APIENTRY*)(GLenum, GLuint)) _window->getFunction(_funcBeginQueryARB);
02316 _glEndQueryARB = (void (OSG_APIENTRY*)(GLenum)) _window->getFunction(_funcEndQueryARB);
02317 _glGetQueryObjectuivARB = (void (OSG_APIENTRY*)(GLuint, GLenum, GLuint*)) _window->getFunction(_funcGetQueryObjectuivARB);
02318 }
02319
02320 _uiMatrixId = 1;
02321
02322 _currMatrix.first = 1;
02323 _currMatrix.second.setIdentity();
02324
02325 _visibilityStack.clear();
02326 _visibilityStack.push_back(FrustumVolume::P_NONE);
02327
02328 bool full = false;
02329
02330 if(_viewport != NULL)
02331 {
02332 if(_camera != NULL)
02333 {
02334 if(_bSmallFeatureCulling)
02335 _camera->getWorldToScreen(_worldToScreenMatrix, *_viewport);
02336
02337 _camera->setupProjection(this, *_viewport);
02338
02339
02340
02341 _camera->getViewing(_currMatrix.second,
02342 _viewport->getPixelWidth (),
02343 _viewport->getPixelHeight());
02344
02345 _camInverse.invertFrom(_currMatrix.second);
02346
02347 glMatrixMode(GL_MODELVIEW);
02348 }
02349
02350 if(_background != NULL)
02351 {
02352 _background->clear(this, _viewport);
02353 }
02354 }
02355
02356 updateTopMatrix();
02357
02358 _mMatMap.clear();
02359
02360 _pNodeFactory->freeAll();
02361
02362
02363
02364
02365
02366
02367
02368
02369
02370
02371
02372 DrawTreeNode::_iCreateCount = 0;
02373 DrawTreeNode::_iDeleteCount = 0;
02374
02375 _pMatRoots.clear();
02376 _pTransMatRoots.clear();
02377 _pNoStateSortRoot = NULL;
02378 _pNoStateSortTransRoot = NULL;
02379
02380 _ocRoot.clear();
02381
02382 _pActiveState = NULL;
02383
02384 _uiActiveMatrix = 0;
02385
02386 _uiNumMaterialChanges = 0;
02387 _uiNumMatrixChanges = 0;
02388 _uiNumLightChanges = 0;
02389 _uiNumGeometries = 0;
02390 _uiNumTransGeometries = 0;
02391 _uiNumOcclusionTests = 0;
02392 _uiNumOcclusionCulled = 0;
02393
02394 getStatistics()->reset();
02395
02396 _vLights.clear();
02397 _lightsMap.clear();
02398 _lightsState = 0;
02399 _activeLightsState = 0;
02400 _activeLightsCount = 0;
02401 _activeLightsMask = 0;
02402
02403
02404 #if 0
02405 for(UInt32 i=0;i<_lightsTable.size();++i)
02406 {
02407 printf("Lights table: %u : ", i);
02408 for(UInt32 j=0;j<_lightsTable[i].size();++j)
02409 {
02410 printf("%u,", _lightsTable[i][j]);
02411 }
02412 printf("\n");
02413 }
02414 #endif
02415
02416
02417 _lightsTable.clear();
02418 _lightsPath.clear();
02419 _lightEnvsLightsState.clear();
02420
02421
02422 _vClipPlanes.clear();
02423 _clipPlanesMap.clear();
02424 _clipPlanesState = 0;
02425 _activeClipPlanesState = 0;
02426 _activeClipPlanesCount = 0;
02427 _activeClipPlanesMask = 0;
02428
02429 _clipPlanesTable.clear();
02430 _clipPlanesPath.clear();
02431
02432 _stateSorting = true;
02433
02434 return Action::Continue;
02435 }
02436
02437 Action::ResultE RenderAction::stop(ResultE res)
02438 {
02439 getStatistics()->getElem(statDrawTime)->start();
02440
02441 UInt32 i;
02442
02443
02444
02445
02446
02447
02448 if(!_bLocalLights)
02449 {
02450 _activeLightsMask = 0;
02451 for(i = 0; i < _vLights.size(); i++)
02452 {
02453 _activeLightsMask |= (1 << i);
02454 glLoadMatrixf(_vLights[i].second.getValues());
02455 _vLights[i].first->activate(this, i);
02456 ++_uiNumLightChanges;
02457 }
02458 }
02459 else
02460 {
02461
02462 const Color4f black(0.0f, 0.0f, 0.0f, 1.0f);
02463 for(i = 0;i < 8;++i)
02464 {
02465 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE,
02466 black.getValuesRGBA());
02467 glDisable(GL_LIGHT0 + i);
02468 }
02469 }
02470
02471
02472 for(i = 0;i < 6;++i)
02473 glDisable(GL_CLIP_PLANE0 + i);
02474
02475 glDepthMask(GL_TRUE);
02476
02477 if(_pNoStateSortRoot != NULL)
02478 {
02479 draw(_pNoStateSortRoot);
02480 }
02481
02482 if(_bOcclusionCulling && (_occlusionCullingMode & OcclusionStopAndWait) && !_ocRoot.empty())
02483 {
02484 OCMap::reverse_iterator it = _ocRoot.rbegin();
02485
02486 _bOcclusionCulling = false;
02487 draw((*it++).second);
02488 _bOcclusionCulling = true;
02489
02490 while(it != _ocRoot.rend())
02491 draw((*it++).second);
02492 }
02493
02494 if(_pNoStateSortTransRoot != NULL)
02495 {
02496 draw(_pNoStateSortTransRoot);
02497 }
02498
02499
02500 bool bZWriteTrans = _bZWriteTrans;
02501 if(_bOcclusionCulling && (_occlusionCullingMode & OcclusionMultiFrame))
02502 _bZWriteTrans = false;
02503
02504 SortKeyMap::iterator matRootsIt = _pMatRoots.begin();
02505 TransSortKeyMap::iterator transMatRootsIt = _pTransMatRoots.begin();
02506
02507 while(matRootsIt != _pMatRoots.end() ||
02508 transMatRootsIt != _pTransMatRoots.end())
02509 {
02510 bool matRootsValid = (matRootsIt != _pMatRoots.end());
02511 bool transMatRootsValid = (transMatRootsIt != _pTransMatRoots.end());
02512
02513 Int32 matSortKey = matRootsValid ? (*matRootsIt).first : 0;
02514 Int32 transSortKey = transMatRootsValid ? (*transMatRootsIt).first : 0;
02515
02516 if(matRootsValid)
02517 {
02518 if(transMatRootsValid)
02519 {
02520 if(matSortKey <= transSortKey)
02521 {
02522
02523 draw((*matRootsIt).second->getFirstChild());
02524 ++matRootsIt;
02525 }
02526 }
02527 else
02528 {
02529
02530 draw((*matRootsIt).second->getFirstChild());
02531 ++matRootsIt;
02532 }
02533 }
02534
02535 if(transMatRootsValid)
02536 {
02537 if(matRootsValid)
02538 {
02539 if(transSortKey <= matSortKey)
02540 {
02541 if(!_bZWriteTrans)
02542 glDepthMask(GL_FALSE);
02543
02544 TransSortMap &ts = (*transMatRootsIt).second;
02545 for(TransSortMap::iterator it = ts.begin();it != ts.end();++it)
02546 draw((*it).second);
02547
02548
02549 if(!_bZWriteTrans)
02550 glDepthMask(GL_TRUE);
02551 ++transMatRootsIt;
02552 }
02553 }
02554 else
02555 {
02556 if(!_bZWriteTrans)
02557 glDepthMask(GL_FALSE);
02558
02559 TransSortMap &ts = (*transMatRootsIt).second;
02560 for(TransSortMap::iterator it = ts.begin();it != ts.end();++it)
02561 draw((*it).second);
02562
02563
02564 if(!_bZWriteTrans)
02565 glDepthMask(GL_TRUE);
02566 ++transMatRootsIt;
02567 }
02568 }
02569 }
02570
02571 if(_pActiveState != NULL)
02572 {
02573 State *state = _pActiveState;
02574
02575
02576 _pActiveState = NULL;
02577
02578 state->deactivate(this);
02579 }
02580
02581 if(!_bLocalLights)
02582 {
02583 for(i = 0; i < _vLights.size(); ++i)
02584 {
02585 _vLights[i].first->deactivate(this, i);
02586 ++_uiNumLightChanges;
02587 }
02588 }
02589 else
02590 {
02591 const Color4f black(0.0f, 0.0f, 0.0f, 1.0f);
02592 for(i = 0;i < _activeLightsCount;++i)
02593 {
02594 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE,
02595 black.getValuesRGBA());
02596 glDisable(GL_LIGHT0 + i);
02597 }
02598 }
02599
02600 for(i = 0;i < _activeClipPlanesCount;++i)
02601 glDisable(GL_CLIP_PLANE0 + i);
02602
02603 if(_bOcclusionCulling && (_occlusionCullingMode & OcclusionMultiFrame))
02604 {
02605 if(_occlusionCullingMode == OcclusionHierarchicalMultiFrame)
02606 {
02607
02608 std::vector<UInt32> remove;
02609 for(std::set<UInt32>::iterator it=_hier_occlusions.begin();
02610 it!=_hier_occlusions.end();++it)
02611 {
02612 NodePtr node = NodePtr::dcast(FieldContainerFactory::the()->getContainer(*it));
02613 if(node != NullFC)
02614 {
02615 GLuint occlusionQuery = getOcclusionQuery(node);
02616 if(occlusionQuery == 0)
02617 {
02618 setOcclusionMask(node, 0);
02619 remove.push_back(*it);
02620 continue;
02621 }
02622
02623 GLuint pixels = 0;
02624 _glGetQueryObjectuivARB(occlusionQuery, GL_QUERY_RESULT_ARB, &pixels);
02625 ++_uiNumOcclusionTests;
02626
02627
02628 if(pixels > _occlusionCullingPixels)
02629 {
02630
02631 setOcclusionMask(node, 0);
02632 remove.push_back(*it);
02633 continue;
02634 }
02635 else
02636 {
02637
02638 node->setOcclusionMask(1);
02639
02640 for(UInt32 i=0;i<node->getNChildren();++i)
02641 remove.push_back(node->getChild(i).getFieldContainerId());
02642 _occluded_nodes.push_back(node);
02643 ++_uiNumOcclusionCulled;
02644 continue;
02645 }
02646 }
02647 else
02648 {
02649 remove.push_back(*it);
02650 }
02651 }
02652
02653
02654 for(UInt32 i=0;i<remove.size();++i)
02655 _hier_occlusions.erase(remove[i]);
02656
02657
02658 for(std::vector<NodePtr>::iterator it=_occluded_nodes.begin();
02659 it!=_occluded_nodes.end();++it)
02660 {
02661 NodePtr occluded = (*it);
02662 NodePtr parent = occluded->getParent();
02663 if(parent != NullFC)
02664 {
02665 bool all_children_occluded = true;
02666
02667
02668 bool check_all_childs = false;
02669 SwitchPtr sw = SwitchPtr::dcast(parent->getCore());
02670 if(sw != NullFC)
02671 {
02672 Int32 choice = sw->getChoice();
02673 if(choice == -2)
02674 check_all_childs = true;
02675 else if(choice >= 0)
02676 {
02677
02678 NodePtr child = parent->getChild(choice);
02679 if(child != NullFC && child->getOcclusionMask() == 0)
02680 {
02681
02682 if(!hasGeometryChild(child))
02683 child->setOcclusionMask(1);
02684 else
02685 all_children_occluded = false;
02686 }
02687 }
02688
02689 }
02690 else
02691 {
02692 check_all_childs = true;
02693 }
02694
02695 if(check_all_childs)
02696 {
02697 for(UInt32 i=0;i<parent->getNChildren();++i)
02698 {
02699
02700 if(!parent->getChild(i)->getActive())
02701 continue;
02702
02703
02704 NodePtr child = parent->getChild(i);
02705 if(child->getOcclusionMask() == 0)
02706 {
02707
02708 if(!hasGeometryChild(child))
02709 {
02710 child->setOcclusionMask(1);
02711 }
02712 else
02713 {
02714 all_children_occluded = false;
02715
02716 break;
02717 }
02718 }
02719 }
02720 }
02721
02722 if(all_children_occluded)
02723 {
02724 _hier_occlusions.insert(parent.getFieldContainerId());
02725 }
02726 else
02727 {
02728 parent->setOcclusionMask(0);
02729 }
02730 }
02731 }
02732 _occluded_nodes.clear();
02733 }
02734
02735
02736 _bZWriteTrans = bZWriteTrans;
02737
02738 _uiActiveMatrix = 0;
02739
02740
02741
02742
02743 glDepthMask(GL_FALSE);
02744 glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);
02745
02746 resetOcclusionQueryIndex();
02747 _occlusionQueries.clear();
02748
02749
02750 matRootsIt = _pMatRoots.begin();
02751 while(matRootsIt != _pMatRoots.end())
02752 drawMultiFrameOcclusionBB((*matRootsIt++).second->getFirstChild());
02753
02754
02755 transMatRootsIt = _pTransMatRoots.begin();
02756 while(transMatRootsIt != _pTransMatRoots.end())
02757 {
02758 TransSortMap &ts = (*transMatRootsIt++).second;
02759 for(TransSortMap::iterator tsit = ts.begin();tsit != ts.end();++tsit)
02760 drawMultiFrameOcclusionBB((*tsit).second);
02761 }
02762
02763 if(_occlusionCullingMode == OcclusionHierarchicalMultiFrame)
02764 {
02765
02766 Matrix view;
02767 if(_camera != NULL)
02768 {
02769 _camera->getViewing(view,
02770 _viewport->getPixelWidth (),
02771 _viewport->getPixelHeight());
02772 }
02773
02774 for(std::set<UInt32>::iterator it=_hier_occlusions.begin();
02775 it!=_hier_occlusions.end();++it)
02776 {
02777 NodePtr node = NodePtr::dcast(FieldContainerFactory::the()->getContainer(*it));
02778 if(node != NullFC)
02779 drawHierarchicalMultiFrameOcclusionBB(view, node);
02780 }
02781 }
02782
02783 glDepthMask(GL_TRUE);
02784 glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
02785
02786 glFlush();
02787 }
02788
02789 glDepthMask(GL_TRUE);
02790
02791 if(_useGLFinish)
02792 glFinish();
02793
02794 StatTimeElem* elemDraw = getStatistics()->getElem(statDrawTime);
02795 elemDraw->stop();
02796
02797 _viewport->setDrawTime((Real32)elemDraw->getTime());
02798 if(!_ownStat)
02799 {
02800 getStatistics()->getElem(statNMaterials )->set(
02801 _uiNumMaterialChanges);
02802 getStatistics()->getElem(statNMatrices )->set(
02803 _uiNumMatrixChanges);
02804 getStatistics()->getElem(statNLights )->set(
02805 _uiNumLightChanges);
02806 getStatistics()->getElem(statNGeometries )->set(
02807 _uiNumGeometries);
02808 getStatistics()->getElem(statNTransGeometries)->set(
02809 _uiNumTransGeometries);
02810 getStatistics()->getElem(statNOcclusionTests )->set(
02811 _uiNumOcclusionTests);
02812 getStatistics()->getElem(statNOcclusionCulled )->set(
02813 _uiNumOcclusionCulled);
02814
02815 if(_bOcclusionCulling)
02816 {
02817 if(_occlusionCullingMode == OcclusionStopAndWait)
02818 {
02819 getStatistics()->getElem(statNOcclusionMode)->set(
02820 "Stop And Wait");
02821 }
02822 else if(_occlusionCullingMode == OcclusionMultiFrame)
02823 {
02824 getStatistics()->getElem(statNOcclusionMode)->set(
02825 "Multi Frame");
02826 }
02827 else if(_occlusionCullingMode == OcclusionHierarchicalMultiFrame)
02828 {
02829 getStatistics()->getElem(statNOcclusionMode)->set(
02830 "Hier. Multi Frame");
02831 }
02832 }
02833 else
02834 {
02835 getStatistics()->getElem(statNOcclusionMode)->set(
02836 "Off");
02837 }
02838 }
02839
02840
02841
02842
02843
02844
02845
02846
02847
02848 Inherited::stop(res);
02849 return res;
02850 }
02851
02852 void RenderAction::push_matrix(const Matrix &matrix)
02853 {
02854 _vMatrixStack.push_back(_currMatrix);
02855
02856 #ifdef PRINT_MAT
02857 fprintf(stderr, "pushed %d\n", _currMatrix.first);
02858
02859 for(int i = 0; i < 4; i++)
02860 {
02861 fprintf(stderr, "% 5.2f % 5.2f % 5.2f % 5.2f\n",
02862 _currMatrix.second[i][0],
02863 _currMatrix.second[i][1],
02864 _currMatrix.second[i][2],
02865 _currMatrix.second[i][3]);
02866 }
02867 #endif
02868
02869 _currMatrix.first = ++_uiMatrixId;
02870 _currMatrix.second.mult(matrix);
02871 updateTopMatrix();
02872
02873 #ifdef PRINT_MAT
02874 fprintf(stderr, "current %d\n", _currMatrix.first);
02875
02876 for(int i = 0; i < 4; i++)
02877 {
02878 fprintf(stderr, "% 5.2f % 5.2f % 5.2f % 5.2f\n",
02879 _currMatrix.second[i][0],
02880 _currMatrix.second[i][1],
02881 _currMatrix.second[i][2],
02882 _currMatrix.second[i][3]);
02883 }
02884 #endif
02885 }
02886
02887 void RenderAction::pop_matrix(void)
02888 {
02889 #ifdef PRINT_MAT
02890 fprintf(stderr, "pop %d\n", _currMatrix.first);
02891
02892 for(int i = 0; i < 4; i++)
02893 {
02894 fprintf(stderr, "% 5.2f % 5.2f % 5.2f % 5.2f\n",
02895 _currMatrix.second[i][0],
02896 _currMatrix.second[i][1],
02897 _currMatrix.second[i][2],
02898 _currMatrix.second[i][3]);
02899 }
02900 #endif
02901
02902 _currMatrix = _vMatrixStack.back();
02903
02904 _vMatrixStack.pop_back();
02905
02906 #ifdef PRINT_MAT
02907 fprintf(stderr, "current %d\n", _currMatrix.first);
02908
02909 for(int i = 0; i < 4; i++)
02910 {
02911 fprintf(stderr, "% 5.2f % 5.2f % 5.2f % 5.2f\n",
02912 _currMatrix.second[i][0],
02913 _currMatrix.second[i][1],
02914 _currMatrix.second[i][2],
02915 _currMatrix.second[i][3]);
02916 }
02917 #endif
02918 }
02919
02920
02921
02925
02926
02927
02928
02929
02930
02931
02932
02933 std::vector<RenderAction::Functor> *RenderAction::getDefaultEnterFunctors(void)
02934 {
02935 return _vDefaultEnterFunctors;
02936 }
02937
02938 std::vector<RenderAction::Functor> *RenderAction::getDefaultLeaveFunctors(void)
02939 {
02940 return _vDefaultLeaveFunctors;
02941 }
02942
02943
02944
02945
02946
02947
02948
02952
02955
02956
02958
02959
02961
02962
02964
02965
02967
02968
02970
02971
02973
02974
02976