void OcclusionCullingTreeBuilder::drawNode(OCRenderTreeNode *pNode, DrawEnv &denv, RenderPartitionBase *part) { leaveTesting(denv, part); 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; } //STATE ACTIVATION State *pNewState = pNode->getState(); StateOverride *pNewStateOverride = pNode->getStateOverride(); denv.setLightState(pNode->getLightState()); denv.activateState(pNewState, pNewStateOverride); pNode->setIsRendered(true); if(_ract->getOcclusionCullingDebug() && pNode->getNode()) { pNode->getNode()->setTravMask( pNode->getNode()->getTravMask() | _ract->getOcclusionVisibleDebugMask() ); } //DRAW DRAW DRAW if(pNode->hasFunctor() == true) { if(part->_bCorrectNegScale) { const Matrix &m = _currMatrix.second; // test for a "flipped" matrix // glFrontFace can give conflicts with the polygon chunk ... if(m[0].cross(m[1]).dot(m[2]) < 0.0) { glFrontFace(GL_CW); } else { glFrontFace(GL_CCW); } } //BoxVolume volume = pNode->getVol(); //drawVolume(volume); pNode->getFunctor()(&denv); } }
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()); } }