void OcclusionCullingTreeBuilder::drawTestResults(DrawEnv             &denv,
                                                  RenderPartitionBase *part)
{
    OCRenderTreeNode* pNode;
    while (!_testPendingNodes.empty())
    {
        pNode = _testPendingNodes.front();
        //DRAW DRAW DRAW
        if(pNode->hasFunctor() == true && !pNode->getIsRendered())
        {
            Window* win = denv.getWindow();
            GetQueryObjectuivT getquiv =
                reinterpret_cast<GetQueryObjectuivT>(
                    win->getFunction(_funcGetQueryObjectuivARB));
            GLuint available = 0;
            getquiv(_testSamples[pNode->getResultNum()], GL_QUERY_RESULT_AVAILABLE_ARB, &available);
            if (!available)
            {
                //std::cout << "Waiting on " << pNode->getResultNum() << " buf size:" << _testPendingNodes.size() << std::endl;
                return;
            }
            GLuint sampleCount = 1;  //XXX: Set to what it should be from calc above.
            getquiv(_testSamples[pNode->getResultNum()], GL_QUERY_RESULT_ARB, &sampleCount);

            if(sampleCount > _visPixelThreshold)
            {
                drawNode(pNode, denv, part);
            }
            else
            {
                StatCollector *sc = _ract->getStatCollector();
                if(sc != NULL)
                    sc->getElem(statNOccInvisible)->inc();

                DrawableStatsAttachment *st =
                    DrawableStatsAttachment::get(pNode->getNode()->getCore());

                st->validate();

                if(sc != NULL)
                    sc->getElem(statNOccTriangles)->
                        add(st->getTriangles());

                if(_ract->getOcclusionCullingDebug() && pNode->getNode())
                {
                    pNode->getNode()->setTravMask(
                        pNode->getNode()->getTravMask() |
                        _ract->getOcclusionCulledDebugMask()
                        );
                }
            }
        }
        //std::cout << "Popped: " << pNode->getResultNum() << " buf size now: " << _testPendingNodes.size() - 1 <<  std::endl;
        _testPendingNodes.pop();
    }
}
示例#2
0
int main(int argc, char *argv[])
{
    osgLogP->setLogLevel(LOG_NOTICE);

    osgInit(argc, argv);

    int winid = setupGLUT(&argc, argv);

    // create a GLUT window
    GLUTWindowPtr gwin = GLUTWindow::create();
    gwin->setId(winid);
    gwin->init();

    osgLogP->setLogLevel(LOG_DEBUG);

    // build the test scene
    NodePtr  pRoot      = Node ::create();
    GroupPtr pRootCore  = Group::create();
    NodePtr  pRayGeo    = Node ::create();
    NodePtr  pScene     = buildGraph();
    GroupPtr pSceneCore = Group::create();

    Time     tStart;
    Time     tStop;
    Time     tDFTotal  = 0.0;
    Time     tDFSTotal = 0.0;
    Time     tPTotal   = 0.0;
    Time     tOTotal   = 0.0;

    StatCollector statP;
    StatCollector statDF;
    StatCollector statDFS;

    beginEditCP(pRoot, Node::CoreFieldId | Node::ChildrenFieldId);
    pRoot->setCore (pRootCore   );
    pRoot->addChild(pScene      );
    pRoot->addChild(pRayGeo     );
    endEditCP  (pRoot, Node::CoreFieldId | Node::ChildrenFieldId);

    createRays(uiNumRays, testRays);

    // build the geometry to visualize the rays
    pPoints = GeoPositions3f::create();
    beginEditCP(pPoints);
    pPoints->addValue(Pnt3f(0.0, 0.0, 0.0));
    pPoints->addValue(Pnt3f(0.0, 0.0, 0.0));
    pPoints->addValue(Pnt3f(0.0, 0.0, 0.0));
    pPoints->addValue(Pnt3f(0.0, 0.0, 0.0));
    pPoints->addValue(Pnt3f(0.0, 0.0, 0.0));
    endEditCP  (pPoints);

    GeoIndicesUI32Ptr pIndices = GeoIndicesUI32::create();
    beginEditCP(pIndices);
    pIndices->addValue(0);
    pIndices->addValue(1);
    pIndices->addValue(2);
    pIndices->addValue(3);
    pIndices->addValue(4);
    endEditCP  (pIndices);

    GeoPLengthsPtr pLengths = GeoPLengthsUI32::create();
    beginEditCP(pLengths);
    pLengths->addValue(2);
    pLengths->addValue(3);
    endEditCP  (pLengths);

    GeoPTypesPtr pTypes = GeoPTypesUI8::create();
    beginEditCP(pTypes);
    pTypes->addValue(GL_LINES    );
    pTypes->addValue(GL_TRIANGLES);
    endEditCP  (pTypes);

    GeoColors3fPtr pColors = GeoColors3f::create();
    beginEditCP(pColors);
    pColors->addValue(Color3f(1.0, 1.0, 1.0));
    pColors->addValue(Color3f(1.0, 0.0, 0.0));
    pColors->addValue(Color3f(1.0, 0.0, 0.0));
    pColors->addValue(Color3f(1.0, 0.0, 0.0));
    pColors->addValue(Color3f(1.0, 0.0, 0.0));
    endEditCP  (pColors);

    SimpleMaterialPtr pMaterial = SimpleMaterial::create();
    beginEditCP(pMaterial);
    pMaterial->setLit(false);
    endEditCP  (pMaterial);

    GeometryPtr pRayGeoCore = Geometry::create();
    beginEditCP(pRayGeoCore);
    pRayGeoCore->setPositions(pPoints  );
    pRayGeoCore->setIndices  (pIndices );
    pRayGeoCore->setLengths  (pLengths );
    pRayGeoCore->setTypes    (pTypes   );
    pRayGeoCore->setColors   (pColors  );
    pRayGeoCore->setMaterial (pMaterial);
    endEditCP  (pRayGeoCore);

    beginEditCP(pRayGeo, Node::CoreFieldId);
    pRayGeo->setCore(pRayGeoCore);
    endEditCP  (pRayGeo, Node::CoreFieldId);

    IntersectActor::regDefaultClassEnter(
        osgTypedFunctionFunctor2CPtr<
            NewActionTypes::ResultE,          NodeCorePtr,
            ActorBase::FunctorArgumentType &              >(enterDefault));


    NewActionBase  *pDFAction  = DepthFirstAction     ::create();
    NewActionBase  *pDFSAction = DepthFirstStateAction::create();
    NewActionBase  *pPAction   = PriorityAction       ::create();
    IntersectActor *pIActorDF  = IntersectActor       ::create();
    IntersectActor *pIActorDFS = IntersectActor       ::create();
    IntersectActor *pIActorP   = IntersectActor       ::create();

    pDFAction ->setStatistics(&statDF );
    pDFSAction->setStatistics(&statDFS);
    pPAction  ->setStatistics(&statP  );

    // IntersectActor with DFS-Action does not need leave calls
    pIActorDFS->setLeaveNodeFlag(false);

    pDFAction ->addActor(pIActorDF );
    pDFSAction->addActor(pIActorDFS);
    pPAction  ->addActor(pIActorP  );

    // create old action
    IntersectAction *pIntAction = IntersectAction ::create();

    // make sure bv are up to date
    pScene->updateVolume();


    SINFO << "-=< Intersect >=-" << endLog;

    std::vector<Line>::iterator itRays  = testRays.begin();
    std::vector<Line>::iterator endRays = testRays.end  ();

    for(; itRays != endRays; ++itRays)
    {
        // DepthFirst

        tStart = getSystemTime();

        pIActorDF->setRay        (*itRays);
        pIActorDF->setMaxDistance(10000.0);
        pIActorDF->reset         (       );

        pDFAction->apply(pScene);

        tStop            =  getSystemTime();
        tDFTotal += (tStop - tStart);

        if(pIActorDF->getHit() == true)
        {
            IntersectResult result;

            result._hit  = true;
            result._pObj = pIActorDF->getHitObject       ();
            result._tri  = pIActorDF->getHitTriangleIndex();
            result._dist = pIActorDF->getHitDistance     ();
            result._time = (tStop - tStart);

            resultsDF.push_back(result);
        }
        else
        {
            IntersectResult result;

            result._hit  = false;
            result._pObj = NullFC;
            result._tri  = -1;
            result._dist = 0.0;
            result._time = (tStop - tStart);

            resultsDF.push_back(result);
        }

        std::string strStatDF;
        statDF.putToString(strStatDF);

        //SINFO << "stat DF:  " << strStatDF << endLog;

        // Depth First State

        tStart = getSystemTime();

        pIActorDFS->setRay        (*itRays);
        pIActorDFS->setMaxDistance(10000.0);
        pIActorDFS->reset         (       );

        pDFSAction->apply(pScene);

        tStop     =  getSystemTime();
        tDFSTotal += (tStop - tStart);

        if(pIActorDFS->getHit() == true)
        {
            IntersectResult result;

            result._hit  = true;
            result._pObj = pIActorDFS->getHitObject       ();
            result._tri  = pIActorDFS->getHitTriangleIndex();
            result._dist = pIActorDFS->getHitDistance     ();
            result._time = (tStop - tStart);

            resultsDFS.push_back(result);
        }
        else
        {
            IntersectResult result;

            result._hit  = false;
            result._pObj = NullFC;
            result._tri  = -1;
            result._dist = 0.0;
            result._time = (tStop - tStart);

            resultsDFS.push_back(result);
        }

        std::string strStatDFS;
        statDFS.putToString(strStatDFS);

        //SINFO << "stat DFS: " << strStatDFS << endLog;

        // Priority

        tStart = getSystemTime();

        pIActorP->setRay        (*itRays);
        pIActorP->setMaxDistance(10000.0);
        pIActorP->reset         (       );

        pPAction->apply(pScene);

        tStop          =  getSystemTime();
        tPTotal += (tStop - tStart);

        if(pIActorP->getHit() == true)
        {
            IntersectResult result;

            result._hit  = true;
            result._pObj = pIActorP->getHitObject       ();
            result._tri  = pIActorP->getHitTriangleIndex();
            result._dist = pIActorP->getHitDistance     ();
            result._time = (tStop - tStart);

            resultsP.push_back(result);
        }
        else
        {
            IntersectResult result;

            result._hit  = false;
            result._pObj = NullFC;
            result._tri  = -1;
            result._dist = 0.0;
            result._time = (tStop - tStart);

            resultsP.push_back(result);
        }

        std::string strStatP;
        statP.putToString(strStatP);

        //SINFO << "stat P:   " << strStatP << endLog;

        // Old

        tStart = getSystemTime();

        pIntAction->setLine(*itRays, 100000);
        pIntAction->apply  (pScene         );

        tStop     =  getSystemTime();
        tOTotal += (tStop - tStart);

        if(pIntAction->didHit() == true)
        {
            IntersectResult result;

            result._hit  = true;
            result._pObj = pIntAction->getHitObject  ();
            result._tri  = pIntAction->getHitTriangle();
            result._dist = pIntAction->getHitT       ();
            result._time = (tStop - tStart);

            resultsO.push_back(result);
        }
        else
        {
            IntersectResult result;

            result._hit  = false;
            result._pObj = NullFC;
            result._tri  = -1;
            result._dist = 0.0;
            result._time = (tStop - tStart);

            resultsO.push_back(result);
        }
    }

    UInt32 DFwins      = 0;
    UInt32 DFwinsHit   = 0;
    UInt32 DFwinsMiss  = 0;

    UInt32 DFSwins     = 0;
    UInt32 DFSwinsHit  = 0;
    UInt32 DFSwinsMiss = 0;

    UInt32 Pwins       = 0;
    UInt32 PwinsHit    = 0;
    UInt32 PwinsMiss   = 0;

    UInt32 Owins       = 0;
    UInt32 OwinsHit    = 0;
    UInt32 OwinsMiss   = 0;

    UInt32 failCount   = 0;
    UInt32 passCount   = 0;
    UInt32 hitCount    = 0;
    UInt32 missCount   = 0;

    for(UInt32 i = 0; i < uiNumRays; ++i)
    {
        bool DFfastest  = ((resultsDF [i]._time <= resultsDFS[i]._time) &&
                           (resultsDF [i]._time <= resultsP  [i]._time) &&
                           (resultsDF [i]._time <= resultsO  [i]._time)   );
        bool DFSfastest = ((resultsDFS[i]._time <= resultsDF [i]._time) &&
                           (resultsDFS[i]._time <= resultsP  [i]._time) &&
                           (resultsDFS[i]._time <= resultsO  [i]._time)   );
        bool Pfastest   = ((resultsP  [i]._time <= resultsDF [i]._time) &&
                           (resultsP  [i]._time <= resultsDFS[i]._time) &&
                           (resultsP  [i]._time <= resultsO  [i]._time)   );
        bool Ofastest   = ((resultsO  [i]._time <= resultsDF [i]._time) &&
                           (resultsO  [i]._time <= resultsDFS[i]._time) &&
                           (resultsO  [i]._time <= resultsP  [i]._time)   );

        if((resultsDF [i]._hit == resultsDFS[i]._hit) &&
           (resultsDFS[i]._hit == resultsP  [i]._hit) &&
           (resultsP  [i]._hit == resultsO  [i]._hit)    )
        {
            if((osgabs(resultsDF [i]._dist - resultsDFS[i]._dist) >= 0.001) ||
               (osgabs(resultsDFS[i]._dist - resultsP  [i]._dist) >= 0.001) ||
               (osgabs(resultsP  [i]._dist - resultsO  [i]._dist) >= 0.001) ||
               (osgabs(resultsO  [i]._dist - resultsDF [i]._dist) >= 0.001)   )
            {
                ++failCount;

                SINFO << "FAIL: df: " << resultsDF [i]._dist
                      << " dfs: "     << resultsDFS[i]._dist
                      << " p: "       << resultsP  [i]._dist
                      << " o: "       << resultsO  [i]._dist
                      << endLog;
                SINFO << "FAIL: df: " << resultsDF [i]._tri
                      << " dfs: "     << resultsDFS[i]._tri
                      << " p: "       << resultsP  [i]._tri
                      << " o: "       << resultsO  [i]._tri
                      << endLog;
            }
            else
            {
                ++passCount;
            }

            if(resultsDF[i]._hit == true)
            {
                ++hitCount;

                DFwinsHit  = DFfastest  ? DFwinsHit  + 1 : DFwinsHit;
                DFSwinsHit = DFSfastest ? DFSwinsHit + 1 : DFSwinsHit;
                PwinsHit   = Pfastest   ? PwinsHit   + 1 : PwinsHit;
                OwinsHit   = Ofastest   ? OwinsHit   + 1 : OwinsHit;
            }
            else
            {
                ++missCount;

                DFwinsMiss  = DFfastest  ? DFwinsMiss  + 1 : DFwinsMiss;
                DFSwinsMiss = DFSfastest ? DFSwinsMiss + 1 : DFSwinsMiss;
                PwinsMiss   = Pfastest   ? PwinsMiss   + 1 : PwinsMiss;
                OwinsMiss   = Ofastest   ? OwinsMiss   + 1 : OwinsMiss;
            }

            DFwins  = DFfastest  ? DFwins  + 1 : DFwins;
            DFSwins = DFSfastest ? DFSwins + 1 : DFSwins;
            Pwins   = Pfastest   ? Pwins   + 1 : Pwins;
            Owins   = Ofastest   ? Owins   + 1 : Owins;
        }
        else
        {
            ++failCount;
        }

        //SINFO << i << " \t" << (DFfastest  ? "D ->" : "    ") << " hit: " << resultsDF [i]._hit << " time: " << resultsDF [i]._time << endLog;
        //SINFO << "  \t"     << (DFSfastest ? "S ->" : "    ") << " hit: " << resultsDFS[i]._hit << " time: " << resultsDFS[i]._time << endLog;
        //SINFO << "  \t"     << (Pfastest   ? "P ->" : "    ") << " hit: " << resultsP  [i]._hit << " time: " << resultsP  [i]._time << endLog;
        //SINFO << "  \t"     << (Ofastest   ? "O ->" : "    ") << " hit: " << resultsO  [i]._hit << " time: " << resultsO  [i]._time << endLog;
    }

    SINFO << " df total:  "    << tDFTotal   << (tDFTotal < tDFSTotal && tDFTotal < tPTotal && tDFTotal < tOTotal ? " *" : "  ") 
          << " wins: "         << DFwins     << " (" << (static_cast<Real32>(DFwins)     / static_cast<Real32>(passCount)) * 100.0 << "%)\t"
          << " wins on hit: "  << DFwinsHit  << " (" << (static_cast<Real32>(DFwinsHit)  / static_cast<Real32>(hitCount )) * 100.0 << "%)\t"
          << " wins on miss: " << DFwinsMiss << " (" << (static_cast<Real32>(DFwinsMiss) / static_cast<Real32>(missCount)) * 100.0 << "%)"
          << endLog;

    SINFO << " dfs total: "    << tDFSTotal  << (tDFSTotal < tDFTotal && tDFSTotal < tPTotal && tDFSTotal < tOTotal ? " *" : "  ") 
          << " wins: "         << DFSwins     << " (" << (static_cast<Real32>(DFSwins)     / static_cast<Real32>(passCount)) * 100.0 << "%)\t"
          << " wins on hit: "  << DFSwinsHit  << " (" << (static_cast<Real32>(DFSwinsHit)  / static_cast<Real32>(hitCount )) * 100.0 << "%)\t"
          << " wins on miss: " << DFSwinsMiss << " (" << (static_cast<Real32>(DFSwinsMiss) / static_cast<Real32>(missCount)) * 100.0 << "%)"
          << endLog;

    SINFO << " p total:   "    << tPTotal   << (tPTotal < tDFTotal && tPTotal < tDFSTotal && tPTotal < tOTotal ? " *" : "  ") 
          << " wins: "         << Pwins     << " (" << (static_cast<Real32>(Pwins)     / static_cast<Real32>(passCount)) * 100.0 << "%)\t"
          << " wins on hit: "  << PwinsHit  << " (" << (static_cast<Real32>(PwinsHit)  / static_cast<Real32>(hitCount )) * 100.0 << "%)\t"
          << " wins on miss: " << PwinsMiss << " (" << (static_cast<Real32>(PwinsMiss) / static_cast<Real32>(missCount)) * 100.0 << "%)"
          << endLog;

    SINFO << " o total:   "    << tOTotal   << (tOTotal < tDFTotal && tOTotal < tDFSTotal && tOTotal < tPTotal ? " *" : "  ") 
          << " wins: "         << Owins     << " (" << (static_cast<Real32>(Owins)     / static_cast<Real32>(passCount)) * 100.0 << "%)\t"
          << " wins on hit: "  << OwinsHit  << " (" << (static_cast<Real32>(OwinsHit)  / static_cast<Real32>(hitCount )) * 100.0 << "%)\t"
          << " wins on miss: " << OwinsMiss << " (" << (static_cast<Real32>(OwinsMiss) / static_cast<Real32>(missCount)) * 100.0 << "%)"
          << endLog;

    SINFO << "pass: "******" fail: " << failCount
          << " hit: " << hitCount  << " miss: " << missCount << endLog;

    osgLogP->setLogLevel(LOG_NOTICE);

#if 0
    // create the SimpleSceneManager helper
    mgr = new SimpleSceneManager;

    // tell the manager what to manage
    mgr->setWindow(gwin );
    mgr->setRoot  (pRoot);

    // show the whole scene
    mgr->showAll();

    // GLUT main loop
    glutMainLoop();
#endif


    return 0;
}
// Initialize GLUT & OpenSG and set up the scene
int main(int argc, char **argv)
{
    // OSG init
    osgInit(argc,argv);

    // GLUT init
    int winid = setupGLUT(&argc, argv);

    // the connection between GLUT and OpenSG
    GLUTWindowPtr gwin= GLUTWindow::create();
    gwin->setId(winid);
    gwin->init();

    // load the scene
    
    if(argc < 2)
    {
        FWARNING(("No file given!\n"));
        FWARNING(("Supported file formats:\n"));
        
        std::list<const char*> suffixes;
        SceneFileHandler::the().getSuffixList(suffixes);
        
        for(std::list<const char*>::iterator it  = suffixes.begin();
                                             it != suffixes.end();
                                           ++it)
        {
            FWARNING(("%s\n", *it));
        }

        std::vector<std::string> suffixesVec;
        suffixesVec = FCFileHandler::the()->getSuffixList();
        
        for(std::vector<std::string>::iterator it  = suffixesVec.begin();
                                             it != suffixesVec.end();
                                           ++it)
        {
            FWARNING(("%s\n", *it));
        }

        RootNodes.push_back( makeTorus(.5, 2, 16, 16) );
        glutSetWindowTitle("No file Loaded");
    }
    else
    {
        glutSetWindowTitle(argv[1]);
        Load(std::string(argv[1]), RootNodes, Cameras);

		if(RootNodes.size() < 1)
		{
			std::cout << "There are no root nodes defined." << std::endl;
			return 0;
		}
    }

    //Create Statistics Foreground
    SimpleStatisticsForegroundPtr TheStatForeground = SimpleStatisticsForeground::create();
    beginEditCP(TheStatForeground);
        TheStatForeground->setSize(25);
        TheStatForeground->setColor(Color4f(0,1,0,0.7));
        TheStatForeground->addElement(RenderAction::statDrawTime, "Draw FPS: %r.3f");
        TheStatForeground->addElement(DrawActionBase::statTravTime, "TravTime: %.3f s");
        TheStatForeground->addElement(RenderAction::statDrawTime, "DrawTime: %.3f s");
        TheStatForeground->addElement(DrawActionBase::statCullTestedNodes, 
                           "%d Nodes culltested");
        TheStatForeground->addElement(DrawActionBase::statCulledNodes, 
                           "%d Nodes culled");
        TheStatForeground->addElement(RenderAction::statNMaterials, 
                           "%d material changes");
        TheStatForeground->addElement(RenderAction::statNMatrices, 
                           "%d matrix changes");
        TheStatForeground->addElement(RenderAction::statNGeometries, 
                           "%d Nodes drawn");
        TheStatForeground->addElement(RenderAction::statNTransGeometries, 
                           "%d transparent Nodes drawn");
        TheStatForeground->addElement(Drawable::statNTriangles, 
                           "%d triangles drawn");
        TheStatForeground->addElement(Drawable::statNLines, 
                           "%d lines drawn");
        TheStatForeground->addElement(Drawable::statNPoints, 
                           "%d points drawn");
        TheStatForeground->addElement(Drawable::statNPrimitives,
                            "%d primitive groups drawn");
        TheStatForeground->addElement(Drawable::statNVertices, 
                           "%d vertices transformed");
        TheStatForeground->addElement(Drawable::statNGeoBytes, "%d bytes of geometry used");
        TheStatForeground->addElement(RenderAction::statNTextures, "%d textures used");
        TheStatForeground->addElement(RenderAction::statNTexBytes, "%d bytes of texture used");
    endEditCP(TheStatForeground);

	//Set up Selection
	SelectedRootNode = 0;
	SelectedCamera = -1;

    // create the SimpleSceneManager helper
    mgr = new SimpleSceneManager;

    // tell the manager what to manage
    mgr->setWindow(gwin );
    mgr->setRoot  (RootNodes[SelectedRootNode]);
    mgr->turnHeadlightOff();

    beginEditCP(mgr->getWindow()->getPort(0), Viewport::ForegroundsFieldMask);
        mgr->getWindow()->getPort(0)->getForegrounds().push_back(TheStatForeground);
    endEditCP(mgr->getWindow()->getPort(0), Viewport::ForegroundsFieldMask);
    StatCollector *collector = &TheStatForeground->getCollector();
    
    // add optional elements
    collector->getElem(Drawable::statNTriangles);
    
    mgr->getAction()->setStatistics(collector);

    // show the whole scene
    mgr->showAll();

    // GLUT main loop
    glutMainLoop();

    return 0;
}
void OcclusionCullingTreeBuilder::drawTestNode(OCRenderTreeNode    *pNode,
                                               DrawEnv             &denv,
                                               RenderPartitionBase *part)
{

    //std::cout << "Front: " << _currSample << " Back: " << _currSampleBack << std::endl;
    while(_testPendingNodes.size() == _numTestSamples - 1)
    {
        drawTestResults(denv, part);
        //std::cout << "NOW:  Front: " << _currSample << " Back: " << _currSampleBack << std::endl;
    }

    //DRAW DRAW DRAW
    Window* win = denv.getWindow();
    pNode->setIsRendered(false);


    if(_ract->getOcclusionCullingDebug() && pNode->getNode())
    {
        pNode->getNode()->setTravMask(
            pNode->getNode()->getTravMask() |
            _ract->getOcclusionTestedDebugMask()
            );
    }

    const BoxVolume &volume = pNode->getVolume();
    Pnt3f min,max;
    volume.getBounds(min, max);
    static GLfloat n[6][3] = {
    {-1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 0.0, 0.0},
    {0.0, -1.0, 0.0}, {0.0, 0.0, 1.0}, {0.0, 0.0, -1.0}
    };
    static GLint faces[6][4] = {
    { 0, 1, 2, 3}, { 3, 2, 6, 7}, { 7, 6, 5, 4},
    { 4, 5, 1, 0}, { 5, 6, 2, 1}, { 7, 4, 0, 3}
    };

    GLfloat v[8][3];
    v[0][0] = v[1][0] = v[2][0] = v[3][0] = min[0];
    v[4][0] = v[5][0] = v[6][0] = v[7][0] = max[0];
    v[0][1] = v[1][1] = v[4][1] = v[5][1] = min[1];
    v[2][1] = v[3][1] = v[6][1] = v[7][1] = max[1];
    v[0][2] = v[3][2] = v[4][2] = v[7][2] = min[2];
    v[1][2] = v[2][2] = v[5][2] = v[6][2] = max[2];


    if(_currSample == _numTestSamples - 1)
    {
        _currSample = 0;
    }
    _currSample++;

    StatCollector *sc = _ract->getStatCollector();
    if(sc != NULL)
        sc->getElem(statNOccTests    )->inc();

    enterTesting(denv, part);
    BeginQueryT beginq = reinterpret_cast<BeginQueryT>(
        win->getFunction(_funcBeginQueryARB));
    //std::cout << "Push: " << _currSample << std::endl;
    pNode->setResultNum(_currSample);
    beginq(GL_SAMPLES_PASSED_ARB, _testSamples[_currSample]);
    glBegin(GL_QUADS);
    for(UInt32 i = 0; i<6; i++)
    {
           glNormal3fv(&n[i][0]);
           glVertex3fv(&v[faces[i][0]][0]);
           glNormal3fv(&n[i][0]);
           glVertex3fv(&v[faces[i][1]][0]);
           glNormal3fv(&n[i][0]);
           glVertex3fv(&v[faces[i][2]][0]);
           glNormal3fv(&n[i][0]);
           glVertex3fv(&v[faces[i][3]][0]);
    }
    glEnd();

    EndQueryT endq = reinterpret_cast<EndQueryT>(
        win->getFunction(_funcEndQueryARB));

    endq(GL_SAMPLES_PASSED_ARB);
    _testPendingNodes.push(pNode);
}
void OcclusionCullingTreeBuilder::testNode(OCRenderTreeNode   *pNode,
                                           DrawEnv             &denv,
                                           RenderPartitionBase *part,
                                           Real32              &scr_percent)
{
    while (pNode != NULL)
    {
    //MATRIX SETUP
        UInt32 uiNextMatrix = pNode->getMatrixStore().first;

        if(uiNextMatrix != 0 && uiNextMatrix != _uiActiveMatrix)
        {
            glLoadMatrixf(pNode->getMatrixStore().second.getValues());

            _uiActiveMatrix = uiNextMatrix;

            _currMatrix.second = pNode->getMatrixStore().second;

            updateTopMatrix(denv);

            denv.setObjectToWorld(_accMatrix);

            ++part->_uiNumMatrixChanges;
        }

        const BoxVolume &volume = pNode->getVolume();
        Pnt3f min,max;

        volume.getBounds(min, max);
        Pnt3f p[8];
        p[0].setValues(min[0],min[1],min[2]);
        p[1].setValues(max[0],min[1],min[2]);
        p[2].setValues(min[0],max[1],min[2]);
        p[3].setValues(min[0],min[1],max[2]);
        p[4].setValues(max[0],max[1],min[2]);
        p[5].setValues(max[0],min[1],max[2]);
        p[6].setValues(min[0],max[1],max[2]);
        p[7].setValues(max[0],max[1],max[2]);

        //std::cout << "OtoW:" << std::endl;
        //std::cout << denv.getObjectToWorld() << std::endl;
        //std::cout << "WtoC:" << std::endl;
        //std::cout << worldToCam << std::endl;
        for(UInt32 i = 0; i<8;i++)
        {
           // std::cout << p[i] << "=>";
            denv.getObjectToWorld().mult    (p[i], p[i]);
            _worldToScreen         .multFull(p[i], p[i]);
            //std::cout << p[i] << "  ";
        }
        min=p[0];
        max=p[0];
        for(UInt32 i = 0; i<8; i++)
        {
           for(UInt32 j=0; j<2; j++)
           {
              if(p[i][j] < min[j])
              {
                min[j] = p[i][j];
              }
              if(p[i][j] > max[j])
              {
                max[j] = p[i][j];
              }
           }
        }
        max[0] = osgClamp(-1.f, max[0], 1.f);
        max[1] = osgClamp(-1.f, max[1], 1.f);
        min[0] = osgClamp(-1.f, min[0], 1.f);
        min[1] = osgClamp(-1.f, min[1], 1.f);

        // cbb is the percent of the screen real estate this would cover
        Real32 cbb = (max[0] - min[0]) * (max[1] - min[1]) / 4.f;

        //std::cout << cur_node << ":" << pix << " ";
        //std::cout << pNode->getScalar() << std::endl;

//Make decision

        if(pNode->hasFunctor() == false) //Nothing to do
        {
            //renderNode
            drawNode(pNode, denv, part);
        }
        else
        {
            //make decision
            //if(0 > 1)
            if(cbb > scr_percent) // Rendering major occluders
            {
                drawNode(pNode, denv, part);
                //scr_percent+=cbb;
            }
            else
            {

                Real32 pcov;
                pcov = sqrt(scr_percent) - sqrt(cbb);
                pcov *= pcov;
                //std::cout << "cbb:" << cbb << " scr_percent:" << scr_percent <<" pcov:" << pcov << std::endl;
                //if(scr_percent - pcov > 0.001)
                if(pcov > _coveredProbThreshold || cbb < 0.001) // If within threshold or reall small
                {
                    //Get triangles
                    DrawableStatsAttachment *st =
                        DrawableStatsAttachment::get(pNode->getNode()->getCore());
                    st->validate();
                    UInt32 triangles = st->getTriangles();

                    if(cbb * _vpWidth * _vpHeight < _minFeatureSize) //small feature culling
                    {
                        StatCollector *sc = _ract->getStatCollector();
                        if(sc != NULL)
                            sc->getElem(statNOccTriangles)->
                                add(triangles);
                        if(_ract->getOcclusionCullingDebug() && pNode->getNode())
                        {
                            pNode->getNode()->setTravMask(
                                pNode->getNode()->getTravMask() |
                                _ract->getOcclusionCulledDebugMask()
                                );
                        }
                        pNode->setIsRendered(true);
                    }
                    else if( triangles <= _minTriangleCount )
                    {
                        drawNode(pNode, denv, part);
                    }
                    else if((_testPendingNodes.size() == _numTestSamples - 1)) // Make sure we have room to draw a test
                    {
                        drawTestResults(denv, part);
                        if(_testPendingNodes.size() == _numTestSamples - 1) // If we are waiting on a result, draw a node
                        {
                            drawNode(pNode, denv, part);
                        }
                        else
                        {
                            drawTestNode(pNode, denv, part); // Made room, go ahead and draw a test node
                        }
                    }
                    else
                    {
                        drawTestNode(pNode, denv, part); //Plenty of room in buffer to draw a test node
                    }
                }
                else
                {
                    drawNode(pNode, denv, part); // Probably not being covered up...draw the real node
                    //scr_percent+=cbb;
                }
            }
            scr_percent += ((1.0 - scr_percent) * cbb);
        }

//DRAW CHILDREN OR GO TO TOP AND DO IT AGAIN
        if(pNode->getFirstChild() != NULL)
        {
            OCRenderTreeNode *child =
                static_cast<OCRenderTreeNode *>(pNode->getFirstChild());

            testNode(child, denv, part, scr_percent);
        }

        pNode = static_cast<OCRenderTreeNode *>(pNode->getBrother());
    }
}
void OcclusionCullingTreeBuilder::draw(DrawEnv             &denv,
                                       RenderPartitionBase *part)
{
#if 1 //CHECK_ENV_ACTION
    //std::cout << "Frame Start" << std::endl;
    Window* win = denv.getWindow();

    if(_sortMode == ModeAdaptiveBucket)
    {
        // Merge all the buckets to a tree
        for(UInt32 i = 0; i < _numBuckets; ++i)
        {
            if(_buckets[i] != NULL)
            {
                _pRoot->addChild(_buckets[i]);
            }
        }
    }

    if(!win->hasExtension(_extOcclusionQuery))
    {
        // Don't have it, just draw the whole tree.
        SLOG << "Missing OCC GL extensions!!" << endLog;

        _uiActiveMatrix = 0;
        Inherited::drawNode(_pRoot, denv, part);

        return;
    }

//SETUP
// done in add, action should never change
//    _ract = dynamic_cast<RenderAction*>(denv.getAction());

    if(!_ract)
    {
        FFATAL(("OcclusionCullingTreeBuilder::draw: Action in denv is not a "
                "RenderAction!\n"));
        return;
    }

    _uiActiveMatrix = 0;
    Real32 screenCoveredPercentage = 0.f;
    if(_ract->getOcclusionCullingQueryBufferSize() != _numTestSamples || !_occInitialized)
    {
        _numTestSamples = _ract->getOcclusionCullingQueryBufferSize();
        //std::cout << "Buf size: " << _numTestSamples << std::endl;
        _testSamples.resize(_numTestSamples);
        //std::cout << "Performing OCC on " << _numNodes << " nodes." << std::endl;

        GenQueryT genquer = reinterpret_cast<GenQueryT>(
            win->getFunction(_funcGenQueriesARB));
        genquer(_numTestSamples, &(_testSamples.front()));
        _occInitialized = true;
    }

    if(!_isOccStateCreated)
    {
        _isOccStateCreated = true;

        // register an exit function to clean up the State object
        addPreFactoryExitFunction(&releaseTestingState);

        // Create an empty state to render test nodes.
        _testingStatePtr = State::create();

        DepthChunkUnrecPtr dc = DepthChunk::create();
        dc->setReadOnly(true);
        _testingStatePtr->addChunk(dc);

        ColorMaskChunkUnrecPtr cc = ColorMaskChunk::create();
        cc->setMaskR(false);
        cc->setMaskG(false);
        cc->setMaskB(false);
        cc->setMaskA(false);
        _testingStatePtr->addChunk(cc);

        PolygonChunkUnrecPtr pc = PolygonChunk::create();
        pc->setCullFace(GL_BACK);
        _testingStatePtr->addChunk(pc);

        commitChanges();
    }

    //glGenQueriesARB(_numNodes, queries);
    //std::cout << "Calculated Pixels" << std::endl;

    _vpWidth  = denv.getPixelWidth();
    _vpHeight = denv.getPixelHeight();

    _worldToScreen = denv.getVPWorldToScreen();

    _testingState = &*_testingStatePtr;


    _minFeatureSize = _ract->getOcclusionCullingMinimumFeatureSize();
    _visPixelThreshold = _ract->getOcclusionCullingVisibilityThreshold();
    _coveredProbThreshold = _ract->getOcclusionCullingCoveredThreshold();
    _minTriangleCount = _ract->getOcclusionCullingMinimumTriangleCount();
    _inTesting = false;

    _currSample = 0;
//DRAW / TEST / RE-DRAW ON BUFFER FULL
    testNode(_pRoot, denv, part, screenCoveredPercentage);

    StatCollector *sc = _ract->getStatCollector();
    if(sc != NULL)
        sc->getElem(statNOccNodes)->add(_numNodes);
    _numNodes=0;
    _uiActiveMatrix = 0;

    leaveTesting(denv, part);

//RESULTS / RE-DRAW
    while( !_testPendingNodes.empty() )
    {
        drawTestResults(denv, part);
    }

    //std::cout << "Calc Pixels" << std::endl;


    if(sc != NULL)
    {
        Real32 percentage =
            Real32(sc->getElem(statNOccInvisible)->get()) /
            Real32(sc->getElem(statNOccTests)->get());
        sc->getElem(statNOccSuccessTestPer)->set(percentage);
    }

    //std::cout << "Real pixels " << std::endl;
    //std::cout << std::endl;

   // screen_covered_percentage = 1.0;
   // drawNode(_pRoot, denv, part, screen_covered_percentage);
    _numNodes=0;
    _currSample = 0;
    //std::cout << "Frame End" << std::endl;
#endif
}
示例#7
0
void VRWindowManager::updateWindows() {
    if (rendering_paused) return;
    auto scene = VRScene::getCurrent();
    if (scene) scene->allowScriptThreads();

    ract->setResetStatistics(false);
    StatCollector* sc = ract->getStatCollector();
    if (sc) {
        sc->reset();
        sc->getElem(VRGlobals::FRAME_RATE.statFPS)->add(VRGlobals::FRAME_RATE.fps);
        sc->getElem(VRGlobals::UPDATE_LOOP1.statFPS)->add(VRGlobals::UPDATE_LOOP1.fps);
        sc->getElem(VRGlobals::UPDATE_LOOP2.statFPS)->add(VRGlobals::UPDATE_LOOP2.fps);
        sc->getElem(VRGlobals::UPDATE_LOOP3.statFPS)->add(VRGlobals::UPDATE_LOOP3.fps);
        sc->getElem(VRGlobals::UPDATE_LOOP4.statFPS)->add(VRGlobals::UPDATE_LOOP4.fps);
        sc->getElem(VRGlobals::UPDATE_LOOP5.statFPS)->add(VRGlobals::UPDATE_LOOP5.fps);
        sc->getElem(VRGlobals::UPDATE_LOOP6.statFPS)->add(VRGlobals::UPDATE_LOOP6.fps);
        sc->getElem(VRGlobals::UPDATE_LOOP7.statFPS)->add(VRGlobals::UPDATE_LOOP7.fps);
        sc->getElem(VRGlobals::RENDER_FRAME_RATE.statFPS)->add(VRGlobals::RENDER_FRAME_RATE.fps);
        sc->getElem(VRGlobals::SLEEP_FRAME_RATE.statFPS)->add(VRGlobals::SLEEP_FRAME_RATE.fps);
        sc->getElem(VRGlobals::SWAPB_FRAME_RATE.statFPS)->add(VRGlobals::SWAPB_FRAME_RATE.fps);
        sc->getElem(VRGlobals::WINDOWS_FRAME_RATE.statFPS)->add(VRGlobals::WINDOWS_FRAME_RATE.fps);
        sc->getElem(VRGlobals::SCRIPTS_FRAME_RATE.statFPS)->add(VRGlobals::SCRIPTS_FRAME_RATE.fps);
        sc->getElem(VRGlobals::PHYSICS_FRAME_RATE.statFPS)->add(VRGlobals::PHYSICS_FRAME_RATE.fps);
        sc->getElem(VRGlobals::GTK1_FRAME_RATE.statFPS)->add(VRGlobals::GTK1_FRAME_RATE.fps);
        sc->getElem(VRGlobals::GTK2_FRAME_RATE.statFPS)->add(VRGlobals::GTK2_FRAME_RATE.fps);
        sc->getElem(VRGlobals::SMCALLBACKS_FRAME_RATE.statFPS)->add(VRGlobals::SMCALLBACKS_FRAME_RATE.fps);
        sc->getElem(VRGlobals::SETUP_FRAME_RATE.statFPS)->add(VRGlobals::SETUP_FRAME_RATE.fps);
        sc->getElem(VRGlobals::SCRIPTS_FRAME_RATE.statFPS)->add(VRGlobals::SCRIPTS_FRAME_RATE.fps);
    }

    //TODO: use barrier->getnumwaiting to make a state machine, allways ensure all are waiting!!

    BarrierRefPtr barrier = Barrier::get("PVR_rendering", true);

    auto updateSceneLinks = [&]() {
        for (auto view : VRSetup::getCurrent()->getViews()) {
            if (auto r = view->getRenderingL()) r->updateSceneLink();
            if (auto r = view->getRenderingR()) r->updateSceneLink();
        }
    };

    auto wait = [&](int timeout = -1) {
        int pID = VRProfiler::get()->regStart("window manager barrier");

        if (timeout > 0) {
            size_t tEnter = time(0);
            while (barrier->getNumWaiting() < VRWindow::active_window_count) {
                usleep(1);
                size_t tNow = time(0);
                int delta = tNow - tEnter;
                if (delta >= timeout) {
                    cout << "WARNING! skipping barrier!" << endl;
                    return false;
                }
            }
        }

        barrier->enter(VRWindow::active_window_count+1);
        VRProfiler::get()->regStop(pID);
        return true;
    };

    //TODO:
    // [0423/180710:WARNING:message_in_transit_queue.cc(18)] Destroying nonempty message queue

    auto tryRender = [&]() {
        if (barrier->getNumWaiting() != VRWindow::active_window_count) return true;
        if (!wait()) return false;
        /** let the windows clear their change lists **/
        if (!wait()) return false;
        auto clist = Thread::getCurrentChangeList();
        auto Ncreated = clist->getNumCreated();
        VRGlobals::NCHANGED = clist->getNumChanged();
        VRGlobals::NCREATED = Ncreated;
        if (Ncreated > 50) doRenderSync = true; // to reduce memory issues with big scenes
        for (auto w : getWindows() ) if (auto win = dynamic_pointer_cast<VRMultiWindow>(w.second)) if (win->getState() == VRMultiWindow::INITIALIZING) win->initialize();
        commitChanges();
        if (!wait()) return false;
        /** let the windows merge the change lists **/
        if (!wait()) return false;
        //if (clist->getNumCreated() > 0) cout << "VRWindowManager::updateWindows " << clist->getNumCreated() << " " << clist->getNumChanged() << endl;
        for (auto w : getWindows() ) if (auto win = dynamic_pointer_cast<VRGtkWindow>(w.second)) win->render();
        clist->clear();
        if (doRenderSync) if (!wait(60)) return false;
        doRenderSync = false;
        return true;
        //sleep(1);
    };

    updateSceneLinks();

    if (!tryRender()) {
        cout << "WARNING! a remote window hangs or something!\n";
        for (auto w : getWindows() ) {
            auto win = dynamic_pointer_cast<VRMultiWindow>(w.second);
            if (!win) continue;
            if (win->isWaiting()) continue;
            cout << "WARNING!  window " << win->getName() << " is hanging, state: " << win->getStateString() << endl;
            WARN("WARNING! Lost connection with " + win->getName());
            win->reset();
        }
    }

    if (scene) scene->blockScriptThreads();
}
/*! Draw the statistics lines.
*/
void SimpleStatisticsForeground::draw(DrawEnv *pEnv, Viewport *pPort)
{
    if(getActive() == false)
        return;

    if(_face == 0)
        initText(getFamily(), getSize());

    if ((getCollector() == NULL) || 
        (!getCollector()->getNumOfElems() && !getMFElementIDs()->size()))
        return; // nothing to do

    Real32  pw = Real32(pPort->getPixelWidth ());
    Real32  ph = Real32(pPort->getPixelHeight());

    if(pw < 1 || ph < 1)
        return;

    glPushAttrib(GL_LIGHTING_BIT | GL_POLYGON_BIT | GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_COLOR_MATERIAL);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND);

    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();

    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity();

    // Set viewport. We want to map one unit to one pixel on the
    // screen. Some sources in the internet say that we should
    // add an offset of -0.375 to prevent rounding errors. Don't
    // know if that is true, but it seems to work.
    glOrtho(0 - 0.375, pw - 0.375, 0 - 0.375, ph - 0.375, 0, 1);

    // retrieve text
    std::vector < std::string > stat;

    StatCollector *col = this->getCollector();
    StatElem      *el;

    if(getMFElementIDs()->size() != 0)
    {
        for(UInt32 i = 0; i < getMFElementIDs()->size(); ++i)
        {
            Int32 id(getElementIDs(i));
            el = ((id >= 0) ? col->getElem(id) : 0);

            stat.resize(stat.size() + 1);
            std::vector < std::string >::iterator str = stat.end() - 1;

            const char  *format = NULL;
            if(i < getMFFormats()->size() && getFormats(i).length())
            {
                format = getFormats(i).c_str();
            }

            if (el)
                el->putToString(*str, format);
            else
                *str = format;
        }
    }
    else    // fallback, show all elements
    {
        for(UInt32 i = 0; i < col->getNumOfElems(); ++i)
        {
            el = col->getElem(i, false);
            if(el)
            {
                std::string desc(el->getDesc()->getName()), eltext;

                el->putToString(eltext);
                desc = desc + " : " + eltext;

                stat.resize(stat.size() + 1);
                std::vector < std::string >::iterator str = stat.end() - 1;
                *str = desc;
            }
        }
    }

    TextLayoutParam layoutParam;
    layoutParam.spacing = 1.1f;
    layoutParam.majorAlignment = TextLayoutParam::ALIGN_BEGIN;
    layoutParam.minorAlignment = TextLayoutParam::ALIGN_BEGIN;

    TextLayoutResult layoutResult;
    _face->layout(stat, layoutParam, layoutResult);

    Real32 scale = 1 / _face->getScale();
    Real32 size = _face->getParam().size;
    Real32 textWidth = layoutResult.textBounds.x() * scale + size + getTextMargin().x() * 2.0f;
    Real32 textHeight = layoutResult.textBounds.y() * scale + size + getTextMargin().y() * 2.0f;

    // Let's do some simple form of layout management
    Real32 orthoX = 0, orthoY = ph;

    switch ( getHorizontalAlign() )
    {
        case Right:
            orthoX = pw - textWidth;
            break;
        case Middle:
            orthoX = (pw - textWidth) * 0.5;
            break;
        case Left:
        default:
            break;
    }

    switch ( getVerticalAlign() )
    {
        case Bottom:
            orthoY = textHeight;
            break;
        case Center:
            orthoY = (ph - textHeight) * 0.5 + textHeight;
            break;
        case Top:
        default:
            break;
    }

    glTranslatef(orthoX, orthoY, 0.0);

    // draw background
    glColor4fv(static_cast<const GLfloat *>(getBgColor().getValuesRGBA()));
    glBegin(GL_QUADS);
        glVertex2f(0, -textHeight);
        glVertex2f(textWidth, -textHeight);
        glVertex2f(textWidth, 0);
        glVertex2f(0, 0);
    glEnd();

    // draw border
    if(getBorderColor().alpha() >= 0.0f)
    {
        glColor4fv(
            static_cast<const GLfloat *>(getBorderColor().getValuesRGBA()));

        glBegin(GL_LINE_LOOP);
            glVertex2f(getBorderOffset().x(), 
                       -textHeight + 1 + getBorderOffset().y());
            glVertex2f(textWidth - 1 - getBorderOffset().x(), 
                       -textHeight + 1 + getBorderOffset().y());
            glVertex2f(textWidth - 1 - getBorderOffset().x(), 
                       -1 - getBorderOffset().y());
            glVertex2f(getBorderOffset().x(), -1 - getBorderOffset().y());
        glEnd();
    }

    glTranslatef( 0.5 * size + getTextMargin().x(), 
                 -0.5 * size - getTextMargin().y(), 
                  0.0);

    _texchunk   ->activate(pEnv);
    _texenvchunk->activate(pEnv);

    // draw text shadow
    glColor4fv(static_cast<const GLfloat *>(getShadowColor().getValuesRGBA()));
    glPushMatrix();
    glTranslatef(getShadowOffset().x(), getShadowOffset().y(), 0);
    glScalef(scale, scale, 1);
    _face->drawCharacters(layoutResult);

    // draw text
    glColor4fv(static_cast<const GLfloat *>(getColor().getValuesRGBA()));
    glPopMatrix();
    glScalef(scale, scale, 1);
    _face->drawCharacters(layoutResult);

    _texchunk   ->deactivate(pEnv);
    _texenvchunk->deactivate(pEnv);

    glMatrixMode(GL_PROJECTION);
    glPopMatrix();

    glMatrixMode(GL_MODELVIEW);
    glPopMatrix();

    glPopAttrib();
}
示例#9
0
	/// \brief Drawing the DynamicTerrain
	Action::ResultE DynamicTerrain::drawPrimitives( DrawActionBase* action )
	{
		// do frustum culling here.. extract frustum from the current camera:
		RenderAction* renderAction = dynamic_cast< RenderAction* >( action );

		if( needInitialize_ )
		{
			if( getHeightData() != NullFC )
			{
				if( getLevelSize() < 3 )
				{
					SWARNING << "DynamicTerrain: LevelSize is below minimum (using default)!" << std::endl;

					setLevelSize( 63 );
				}

				// todo: choose the correct height-/texturedata source:
				geoClipmaps_.initialize( getLevelSize(), &imageHeightSource_, getTextureSource() );
			}
			needInitialize_ = false;
		}

		if( !geoClipmaps_.isValid() )
		{
			// no valid data yet
			return Action::Continue;
		}

		// todo: get the viewport of the RenderAction, check if the camera already has a terrain attachment:
			// if not: create a new TerrainView and attach it to the camera

		// update/render the view
		if( renderAction )
		{
			// frustum culling
			const FrustumVolume& frustum = renderAction->getFrustum();

			// make an update right here:
			Matrix camera  = renderAction->getCameraToWorld();
			Matrix toworld = renderAction->top_matrix();			
			toworld.invert();
			camera.multLeft(toworld);
			Pnt3f eyePoint( camera[ 3 ][ 0 ], camera[ 3 ][ 1 ], camera[ 3 ][ 2 ] );

			// transform the eyePoint to the unscaled sample space:
			const WorldTransformation worldTransform = getWorldTransform();
			const Pnt3f worldOffset( worldTransform.offset[ 0 ], 0.0f, worldTransform.offset[ 1 ] );
			
			const Pnt3f localEyePoint = componentDivide( ( eyePoint - worldOffset ), worldTransform.sampleDistance );

			if( !getDisableUpdate() )
			{
				geoClipmaps_.update( localEyePoint );
			}			
			
			// and now draw what we have:
			ClipmapRenderParameters renderParams;
			
			renderParams.renderAction			= renderAction;
			renderParams.window					= renderAction->getWindow();
			renderParams.viewFrustum			= frustum;
			renderParams.enableFrustumCulling	= getEnableFrustumCulling();
			renderParams.showTransitionRegions	= getShowTransitionRegions();
			renderParams.useVboExtension		= getUseVboExtension();
			renderParams.globalTexture			= globalTexture_;
			renderParams.heightColorTexture		= getHeightColorTexture();
			
			renderParams.worldTransform			= worldTransform;

			ClipmapRenderStatistics renderStats;

			geoClipmaps_.render( renderParams, renderStats );

			if( getShowBoundingBoxes() )
			{
				//drawBox( 
			}

			// update stats:
			StatCollector* statCollector = action->getStatistics();
			
			if( statCollector ) 
			{
				StatIntElem* statTriangleCount = statCollector->getElem( Drawable::statNTriangles, false );
				StatIntElem* statVertexCount = statCollector->getElem( Drawable::statNVertices, false );

				if( statTriangleCount )
				{
					statTriangleCount->add( renderStats.drawnTriangleCount );
				}
				if( statVertexCount )
				{
					statVertexCount->add( renderStats.transformedVertexCount );
				}
			}
		}
		else
		{
			//todo: can this ever happen?!
			SLOG << "Test\n";
		}

		return Action::Continue;
	}