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();
    }
}
void DrawableStatsAttachment::invalidate(FieldContainer *obj)
{
    if(obj == NULL)
        return;

    AttachmentContainer *cont = dynamic_cast<AttachmentContainer *>(obj);

    // Called on a non-AttachmentContainer?
    if(cont == NULL)
        return;

    // Find the attachment
    DrawableStatsAttachment *st = get(cont);

    if(st == NULL) // Found the end of the chain
        return;

    // Invalidate it
    st->reset();

    // Traverse upwards
    if(st->getMFParents()->size())
    {
        // Can't have more than 1
        FieldContainer *p = 
            dynamic_cast<FieldContainer *>(st->getParents(0)); 

        // Is this attached to a NodeCore?
        NodeCore *c = dynamic_cast<NodeCore *>(p);
        if(c != NULL)
        {
            MFParentFieldContainerPtr::const_iterator pnI;

            for(  pnI  = c->getMFParents()->begin();
                  pnI != c->getMFParents()->end  ();
                ++pnI)
            {
                Node *node = dynamic_cast<Node *>(*pnI);

                invalidate(node);
            }
        }

        // Is this attached to a Node?
        Node *n = dynamic_cast<Node *>(p);

        if(n != NULL)
        {
            Node *par = n->getParent();

            invalidate(par);
        }
    }
}
void DrawableStatsAttachmentBase::execSyncV(      FieldContainer    &oFrom,
                                        ConstFieldMaskArg  whichField,
                                        AspectOffsetStore &oOffsets,
                                        ConstFieldMaskArg  syncMode,
                                  const UInt32             uiSyncInfo)
{
    DrawableStatsAttachment *pThis = static_cast<DrawableStatsAttachment *>(this);

    pThis->execSync(static_cast<DrawableStatsAttachment *>(&oFrom),
                    whichField,
                    oOffsets,
                    syncMode,
                    uiSyncInfo);
}
void RenderPartition::dropFunctor(DrawFunctor &drawFunc,
                                  State       *pState,
                                  Int32        iSortKey,
                                  bool         bIgnoreOverrides)
{
    if(_eMode == SimpleCallback)
        return;

    RenderAction  *ract    = dynamic_cast<RenderAction *>(_oDrawEnv.getAction());
    Node          *actNode = ract   ->getActNode();
    NodeCore      *actCore = actNode->getCore   ();

    bool           bOverrodeState = false;
    StateOverride *pStateOverride = NULL;

    DrawableStatsAttachment *st = DrawableStatsAttachment::get(actCore);

    if(st == NULL)
    {
        DrawableStatsAttachment::addTo(actCore);

        st = DrawableStatsAttachment::get(actCore);
    }

    st->validate();

    if(_oDrawEnv.getStatCollector() != NULL)
    {
        _oDrawEnv.getStatCollector()->getElem(
            RenderAction::statNTriangles)->add(st->getTriangles());
    }

    _uiNumTriangles += st->getTriangles();

    #ifdef OSG_NEW_SHADER
    bOverrodeState = pushShaderState(pState);
#endif // OSG_NEW_SHADER

    if(_sStateOverrides.top()->empty() == false &&
       bIgnoreOverrides                == false   )
    {
        pStateOverride = _sStateOverrides.top();
    }

    bool bTransparent =
        (pState->isTransparent()                                         ) ||
        (pStateOverride != NULL ? pStateOverride->isTransparent() : false);

    if(_bSortTrans == true && bTransparent == true)
    {
        BuildKeyMapIt mapIt = _mTransMatTrees.lower_bound(iSortKey);

        if(mapIt == _mTransMatTrees.end() || mapIt->first != iSortKey)
        {
            TreeBuilderBase *pBuilder =
                _pTreeBuilderPool->create<DepthSortTreeBuilder>();

            pBuilder->setNodePool(_pNodePool);

            mapIt = _mTransMatTrees.insert(
                mapIt, BuildKeyMap::value_type(iSortKey, pBuilder));
        }

        if(mapIt->second == NULL)
        {
            TreeBuilderBase *pBuilder =
                _pTreeBuilderPool->create<DepthSortTreeBuilder>();

            pBuilder->setNodePool(_pNodePool);
            
            mapIt->second = pBuilder;
        }

        mapIt->second->add(_oDrawEnv.getAction(),
                           this,
                           drawFunc,
                           pState,
                           pStateOverride);
    }
    else if(ract != NULL && ract->getOcclusionCulling() == true)
    {
        BuildKeyMapIt mapIt = _mMatTrees.lower_bound(iSortKey);

        if(mapIt == _mMatTrees.end() || mapIt->first != iSortKey)
        {
            TreeBuilderBase *pBuilder =
                _pTreeBuilderPool->create<OcclusionCullingTreeBuilder>();

            pBuilder->setNodePool(_pNodePool);

            mapIt = _mMatTrees.insert(mapIt,
                                      std::make_pair(iSortKey, pBuilder));
        }

        if(mapIt->second == NULL)
        {
            mapIt->second =
                _pTreeBuilderPool->create<OcclusionCullingTreeBuilder>();

            mapIt->second->setNodePool(_pNodePool);
        }
       
        mapIt->second->add(_oDrawEnv.getAction(),
                           this,
                           drawFunc,
                           pState,
                           pStateOverride);
    }
    else
    {
        BuildKeyMapIt mapIt = _mMatTrees.lower_bound(iSortKey);

        if(mapIt == _mMatTrees.end() || mapIt->first != iSortKey)
        {
            TreeBuilderBase *pBuilder =
                _pTreeBuilderPool->create<StateSortTreeBuilder>();

            pBuilder->setNodePool(_pNodePool);

            mapIt = _mMatTrees.insert(
                mapIt, BuildKeyMap::value_type(iSortKey, pBuilder));
        }

        if(mapIt->second == NULL)
        {
            mapIt->second = 
                _pTreeBuilderPool->create<StateSortTreeBuilder>();

            mapIt->second->setNodePool(_pNodePool);
        }

        mapIt->second->add(_oDrawEnv.getAction(),
                           this,
                           drawFunc,
                           pState,
                           pStateOverride);
    }

#ifdef OSG_NEW_SHADER
    if(bOverrodeState == true)
    {
        this->popState();
    }
#endif
}
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());
    }
}