bool ShadowVolume::getLightPositionalState( osgUtil::CullVisitor& cv, const Light* light, Vec4& lightPos, Vec3& lightDir ) { if( !light ) return false; // get positional state osgUtil::RenderStage* rs = cv.getRenderStage(); osgUtil::PositionalStateContainer::AttrMatrixList& aml = rs->getPositionalStateContainer()->getAttrMatrixList(); RefMatrix* matrix = NULL; bool found = false; // find the light and its matrix // note: it finds the last light occurence with its associated matrix for( osgUtil::PositionalStateContainer::AttrMatrixList::iterator itr = aml.begin(); itr != aml.end(); ++itr ) { const Light* l = dynamic_cast< const Light* >( itr->first.get() ); if( l && l == light ) { found = true; matrix = itr->second.get(); } } if( !found ) return false; // transform light to world space Matrix localToWorld = Matrix::inverse( *cv.getModelViewMatrix() ); if( matrix ) localToWorld.preMult( *matrix ); lightPos = light->getPosition(); if( lightPos[3] == 0 ) lightDir.set( -lightPos[0], -lightPos[1], -lightPos[2] ); else lightDir = light->getDirection(); lightPos = lightPos * localToWorld; lightDir = Matrix::transform3x3( lightDir, localToWorld ); lightDir.normalize(); return true; }
void ParallelSplitShadowMap::cull(osgUtil::CullVisitor& cv){ // record the traversal mask on entry so we can reapply it later. unsigned int traversalMask = cv.getTraversalMask(); osgUtil::RenderStage* orig_rs = cv.getRenderStage(); #ifdef SHADOW_TEXTURE_GLSL PSSMShadowSplitTextureMap::iterator it=_PSSMShadowSplitTextureMap.begin(); #else // do traversal of shadow receiving scene which does need to be decorated by the shadow map for (PSSMShadowSplitTextureMap::iterator it=_PSSMShadowSplitTextureMap.begin();it!=_PSSMShadowSplitTextureMap.end();it++) #endif { PSSMShadowSplitTexture pssmShadowSplitTexture = it->second; cv.pushStateSet(pssmShadowSplitTexture._stateset.get()); ////////////////////////////////////////////////////////////////////////// // DEBUG if ( _displayTexturesGroupingNode ) { cv.pushStateSet(pssmShadowSplitTexture._debug_stateset.get()); } ////////////////////////////////////////////////////////////////////////// _shadowedScene->osg::Group::traverse(cv); cv.popStateSet(); } // need to compute view frustum for RTT camera. // get the bounds of the model. osg::ComputeBoundsVisitor cbbv(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN); cbbv.setTraversalMask(getShadowedScene()->getCastsShadowTraversalMask()); _shadowedScene->osg::Group::traverse(cbbv); ////////////////////////////////////////////////////////////////////////// const osg::Light* selectLight = 0; /// light pos and light direction osg::Vec4 lightpos; osg::Vec3 lightDirection; if ( ! _userLight ) { // try to find a light in the scene osgUtil::PositionalStateContainer::AttrMatrixList& aml = orig_rs->getPositionalStateContainer()->getAttrMatrixList(); for(osgUtil::PositionalStateContainer::AttrMatrixList::iterator itr = aml.begin(); itr != aml.end(); ++itr) { const osg::Light* light = dynamic_cast<const osg::Light*>(itr->first.get()); if (light) { osg::RefMatrix* matrix = itr->second.get(); if (matrix) lightpos = light->getPosition() * (*matrix); else lightpos = light->getPosition(); if (matrix) lightDirection = light->getDirection() * (*matrix); else lightDirection = light->getDirection(); selectLight = light; } } osg::Matrix eyeToWorld; eyeToWorld.invert(*cv.getModelViewMatrix()); lightpos = lightpos * eyeToWorld; lightDirection = lightDirection * eyeToWorld; }else{ // take the user light as light source lightpos = _userLight->getPosition(); lightDirection = _userLight->getDirection(); selectLight = _userLight.get(); } if (selectLight) { // do traversal of shadow receiving scene which does need to be decorated by the shadow map //unsigned int iMaxSplit = _PSSMShadowSplitTextureMap.size(); for (PSSMShadowSplitTextureMap::iterator it=_PSSMShadowSplitTextureMap.begin();it!=_PSSMShadowSplitTextureMap.end();it++) { PSSMShadowSplitTexture pssmShadowSplitTexture = it->second; ////////////////////////////////////////////////////////////////////////// // SETUP pssmShadowSplitTexture for rendering // lightDirection.normalize(); pssmShadowSplitTexture._lightDirection = lightDirection; pssmShadowSplitTexture._cameraView = cv.getRenderInfo().getView()->getCamera()->getViewMatrix(); pssmShadowSplitTexture._cameraProj = cv.getRenderInfo().getView()->getCamera()->getProjectionMatrix(); ////////////////////////////////////////////////////////////////////////// // CALCULATE // Calculate corner points of frustum split // // To avoid edge problems, scale the frustum so // that it's at least a few pixels larger // osg::Vec3d pCorners[8]; calculateFrustumCorners(pssmShadowSplitTexture,pCorners); // Init Light (Directional Light) // calculateLightInitialPosition(pssmShadowSplitTexture,pCorners); // Calculate near and far for light view // calculateLightNearFarFormFrustum(pssmShadowSplitTexture,pCorners); // Calculate view and projection matrices // calculateLightViewProjectionFormFrustum(pssmShadowSplitTexture,pCorners); ////////////////////////////////////////////////////////////////////////// // set up shadow rendering camera pssmShadowSplitTexture._camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF); ////////////////////////////////////////////////////////////////////////// // DEBUG if ( _displayTexturesGroupingNode ) { pssmShadowSplitTexture._debug_camera->setViewMatrix(pssmShadowSplitTexture._camera->getViewMatrix()); pssmShadowSplitTexture._debug_camera->setProjectionMatrix(pssmShadowSplitTexture._camera->getProjectionMatrix()); pssmShadowSplitTexture._debug_camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF); } ////////////////////////////////////////////////////////////////////////// // compute the matrix which takes a vertex from local coords into tex coords // will use this later to specify osg::TexGen.. osg::Matrix MVPT = pssmShadowSplitTexture._camera->getViewMatrix() * pssmShadowSplitTexture._camera->getProjectionMatrix() * osg::Matrix::translate(1.0,1.0,1.0) * osg::Matrix::scale(0.5,0.5,0.5); pssmShadowSplitTexture._texgen->setMode(osg::TexGen::EYE_LINEAR); pssmShadowSplitTexture._texgen->setPlanesFromMatrix(MVPT); ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// cv.setTraversalMask( traversalMask & getShadowedScene()->getCastsShadowTraversalMask() ); // do RTT camera traversal pssmShadowSplitTexture._camera->accept(cv); ////////////////////////////////////////////////////////////////////////// // DEBUG if ( _displayTexturesGroupingNode ) { pssmShadowSplitTexture._debug_camera->accept(cv); } orig_rs->getPositionalStateContainer()->addPositionedTextureAttribute(pssmShadowSplitTexture._textureUnit, cv.getModelViewMatrix(), pssmShadowSplitTexture._texgen.get()); } } // if light // reapply the original traversal mask cv.setTraversalMask( traversalMask ); }
void ShadowMap::cull(osgUtil::CullVisitor& cv) { // record the traversal mask on entry so we can reapply it later. unsigned int traversalMask = cv.getTraversalMask(); osgUtil::RenderStage* orig_rs = cv.getRenderStage(); // do traversal of shadow receiving scene which does need to be decorated by the shadow map { cv.pushStateSet(_stateset.get()); _shadowedScene->osg::Group::traverse(cv); cv.popStateSet(); } // need to compute view frustum for RTT camera. // 1) get the light position // 2) get the center and extents of the view frustum const osg::Light* selectLight = 0; osg::Vec4 lightpos; osg::Vec3 lightDir; //MR testing giving a specific light osgUtil::PositionalStateContainer::AttrMatrixList& aml = orig_rs->getPositionalStateContainer()->getAttrMatrixList(); for(osgUtil::PositionalStateContainer::AttrMatrixList::iterator itr = aml.begin(); itr != aml.end(); ++itr) { const osg::Light* light = dynamic_cast<const osg::Light*>(itr->first.get()); if (light) { if( _light.valid()) { if( _light.get() == light ) selectLight = light; else continue; } else selectLight = light; osg::RefMatrix* matrix = itr->second.get(); if (matrix) { lightpos = light->getPosition() * (*matrix); lightDir = osg::Matrix::transform3x3( light->getDirection(), *matrix ); } else { lightpos = light->getPosition(); lightDir = light->getDirection(); } } } osg::Matrix eyeToWorld; eyeToWorld.invert(*cv.getModelViewMatrix()); lightpos = lightpos * eyeToWorld; lightDir = osg::Matrix::transform3x3( lightDir, eyeToWorld ); lightDir.normalize(); if (selectLight) { // set to ambient on light to black so that the ambient bias uniform can take it's affect const_cast<osg::Light*>(selectLight)->setAmbient(osg::Vec4(0.0f,0.0f,0.0f,1.0f)); //std::cout<<"----- VxOSG::ShadowMap selectLight spot cutoff "<<selectLight->getSpotCutoff()<<std::endl; float fov = selectLight->getSpotCutoff() * 2; if(fov < 180.0f) // spotlight, then we don't need the bounding box { osg::Vec3 position(lightpos.x(), lightpos.y(), lightpos.z()); _camera->setProjectionMatrixAsPerspective(fov, 1.0, 0.1, 1000.0); _camera->setViewMatrixAsLookAt(position,position+lightDir,computeOrthogonalVector(lightDir)); } else { // get the bounds of the model. osg::ComputeBoundsVisitor cbbv(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN); cbbv.setTraversalMask(getShadowedScene()->getCastsShadowTraversalMask()); _shadowedScene->osg::Group::traverse(cbbv); osg::BoundingBox bb = cbbv.getBoundingBox(); if (lightpos[3]!=0.0) // point light { osg::Vec3 position(lightpos.x(), lightpos.y(), lightpos.z()); float centerDistance = (position-bb.center()).length(); float znear = centerDistance-bb.radius(); float zfar = centerDistance+bb.radius(); float zNearRatio = 0.001f; if (znear<zfar*zNearRatio) znear = zfar*zNearRatio; float top = (bb.radius()/centerDistance)*znear; float right = top; _camera->setProjectionMatrixAsFrustum(-right,right,-top,top,znear,zfar); _camera->setViewMatrixAsLookAt(position,bb.center(),computeOrthogonalVector(bb.center()-position)); } else // directional light { // make an orthographic projection osg::Vec3 lightDir(lightpos.x(), lightpos.y(), lightpos.z()); lightDir.normalize(); // set the position far away along the light direction osg::Vec3 position = bb.center() + lightDir * bb.radius() * 2; float centerDistance = (position-bb.center()).length(); float znear = centerDistance-bb.radius(); float zfar = centerDistance+bb.radius(); float zNearRatio = 0.001f; if (znear<zfar*zNearRatio) znear = zfar*zNearRatio; float top = bb.radius(); float right = top; _camera->setProjectionMatrixAsOrtho(-right, right, -top, top, znear, zfar); _camera->setViewMatrixAsLookAt(position,bb.center(),computeOrthogonalVector(lightDir)); } } cv.setTraversalMask( traversalMask & getShadowedScene()->getCastsShadowTraversalMask() ); // do RTT camera traversal _camera->accept(cv); _texgen->setMode(osg::TexGen::EYE_LINEAR); #if IMPROVE_TEXGEN_PRECISION // compute the matrix which takes a vertex from local coords into tex coords // We actually use two matrices one used to define texgen // and second that will be used as modelview when appling to OpenGL _texgen->setPlanesFromMatrix( _camera->getProjectionMatrix() * osg::Matrix::translate(1.0,1.0,1.0) * osg::Matrix::scale(0.5f,0.5f,0.5f) ); // Place texgen with modelview which removes big offsets (making it float friendly) osg::RefMatrix * refMatrix = new osg::RefMatrix ( _camera->getInverseViewMatrix() * *cv.getModelViewMatrix() ); cv.getRenderStage()->getPositionalStateContainer()-> addPositionedTextureAttribute( _shadowTextureUnit, refMatrix, _texgen.get() ); #else // compute the matrix which takes a vertex from local coords into tex coords // will use this later to specify osg::TexGen.. osg::Matrix MVPT = _camera->getViewMatrix() * _camera->getProjectionMatrix() * osg::Matrix::translate(1.0,1.0,1.0) * osg::Matrix::scale(0.5f,0.5f,0.5f); _texgen->setPlanesFromMatrix(MVPT); orig_rs->getPositionalStateContainer()->addPositionedTextureAttribute(_shadowTextureUnit, cv.getModelViewMatrix(), _texgen.get()); #endif } // if(selectLight) // reapply the original traversal mask cv.setTraversalMask( traversalMask ); }
void SoftShadowMap::cull(osgUtil::CullVisitor& cv) { // record the traversal mask on entry so we can reapply it later. unsigned int traversalMask = cv.getTraversalMask(); osgUtil::RenderStage* orig_rs = cv.getRenderStage(); // do traversal of shadow receiving scene which does need to be decorated by the shadow map { cv.pushStateSet(_stateset.get()); _shadowedScene->osg::Group::traverse(cv); cv.popStateSet(); } // need to compute view frustum for RTT camera. // 1) get the light position // 2) get the center and extents of the view frustum const osg::Light* selectLight = 0; osg::Vec4 lightpos; osgUtil::PositionalStateContainer::AttrMatrixList& aml = orig_rs->getPositionalStateContainer()->getAttrMatrixList(); for(osgUtil::PositionalStateContainer::AttrMatrixList::iterator itr = aml.begin(); itr != aml.end(); ++itr) { const osg::Light* light = dynamic_cast<const osg::Light*>(itr->first.get()); if (light) { osg::RefMatrix* matrix = itr->second.get(); if (matrix) lightpos = light->getPosition() * (*matrix); else lightpos = light->getPosition(); selectLight = light; } } osg::Matrix eyeToWorld; eyeToWorld.invert(*cv.getModelViewMatrix()); lightpos = lightpos * eyeToWorld; if (selectLight) { // get the bounds of the model. osg::ComputeBoundsVisitor cbbv(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN); cbbv.setTraversalMask(getShadowedScene()->getCastsShadowTraversalMask()); _shadowedScene->osg::Group::traverse(cbbv); osg::BoundingBox bb = cbbv.getBoundingBox(); osg::Vec3 position; if (lightpos[3]!=0.0) { position.set(lightpos.x(), lightpos.y(), lightpos.z()); } else { // make an orthographic projection osg::Vec3 lightDir(lightpos.x(), lightpos.y(), lightpos.z()); lightDir.normalize(); // set the position far away along the light direction position = lightDir * bb.radius() * 20; } float centerDistance = (position-bb.center()).length(); float znear = centerDistance-bb.radius(); float zfar = centerDistance+bb.radius(); float zNearRatio = 0.001f; if (znear<zfar*zNearRatio) znear = zfar*zNearRatio; float top = bb.radius(); float right = top; _camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF); _camera->setProjectionMatrixAsOrtho(-right, right, -top, top, znear, zfar); _camera->setViewMatrixAsLookAt(position, bb.center(), osg::Vec3(0.0f,1.0f,0.0f)); // compute the matrix which takes a vertex from local coords into tex coords // will use this later to specify osg::TexGen.. osg::Matrix MVPT = _camera->getViewMatrix() * _camera->getProjectionMatrix() * osg::Matrix::translate(1.0,1.0,1.0) * osg::Matrix::scale(0.5,0.5,0.5+_bias); _texgen->setMode(osg::TexGen::EYE_LINEAR); _texgen->setPlanesFromMatrix(MVPT); cv.setTraversalMask( traversalMask & getShadowedScene()->getCastsShadowTraversalMask() ); // do RTT camera traversal _camera->accept(cv); orig_rs->getPositionalStateContainer()->addPositionedTextureAttribute(_textureUnit, cv.getModelViewMatrix(), _texgen.get()); } // reapply the original traversal mask cv.setTraversalMask( traversalMask ); }
void ShadowVolume::cull( osgUtil::CullVisitor& cv ) { //notify(NOTICE)<<"CULL BEGIN"<<std::endl; // if no light, render scene default way if( !_light ) { _shadowedScene->Group::traverse( cv ); return; } // pass 4: add light using stencil // The pass is culled in the first place as it is always culled (in contrary to pass 1). // Its traversed lights are used in following getLightPositionalState. // Note: traversing order of passes 1 to 4 does not matter. Rendering order is given // by RenderBin's setRenderBinDetails(). cv.pushStateSet( _ss4 ); _shadowedScene->Group::traverse( cv ); cv.popStateSet(); // clear stencil buffer - bin number 1 schedules it before 2nd and 3rd pass if( _clearStencil) //_clearDrawable->setBufferMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); cv.addDrawable( _clearDrawable, cv.getModelViewMatrix() ); // pass 1: ambient pass if(!_ambientPassDisabled) { cv.pushStateSet( _ss1 ); _shadowedScene->Group::traverse( cv ); cv.popStateSet(); } // get light positional state, // if no light, return Vec4 lightPos; Vec3 lightDir; if( !getLightPositionalState( cv, _light, lightPos, lightDir ) ) return; /******************PASS 2,3/: Shadow geometry into stencil buffer*********************/ if( _mode == ShadowVolumeGeometryGenerator::CPU_FIND_GPU_EXTRUDE || _mode == ShadowVolumeGeometryGenerator::GPU_RAW || _mode == ShadowVolumeGeometryGenerator::GPU_SILHOUETTE) { //notify(NOTICE)<<"LIGHTPOS: "<<lightPos.x()<<" "<<lightPos.y()<<" "<<lightPos.z()<<" "<<std::endl; _lightPosUniform->set(lightPos); } if(_updateStrategy == UPDATE_EACH_FRAME) _svgg.dirty(); if(_svgg.isDirty()){ //_svgg.clearGeometry(); _svgg.setup(lightPos); _shadowedScene->Group::traverse( _svgg ); } if(_mode == ShadowVolumeGeometryGenerator::SILHOUETTES_ONLY){ cv.pushStateSet(_ssd); ref_ptr< Drawable > d = _svgg.createGeometry(); d->setUseDisplayList( false ); ref_ptr< Geode > geode = new Geode; geode->addDrawable( d ); geode->accept( cv ); cv.popStateSet(); return; } bool twoSidedStencil = _stencilImplementation == STENCIL_TWO_SIDED; if( _stencilImplementation == STENCIL_AUTO ) { GraphicsContext *gc = cv.getState()->getGraphicsContext(); if( gc->isGLExtensionSupported( 2.0, "GL20_separate_stencil" ) || gc->isGLExtensionSupported( "GL_EXT_stencil_two_side" ) || gc->isGLExtensionSupported( "GL_ATI_separate_stencil" ) ) { twoSidedStencil = true; } } if(twoSidedStencil){ cv.pushStateSet( _ss23 ); ref_ptr< Drawable > d = _svgg.createGeometry(); d->setUseDisplayList( false ); ref_ptr< Geode > geode = new Geode; geode->addDrawable( d ); geode->accept( cv ); cv.popStateSet(); if(_svgg.getMethod() == ShadowVolumeGeometryGenerator::ZFAIL){ if( _svgg.getMode() == ShadowVolumeGeometryGenerator::CPU_RAW || _svgg.getMode() == ShadowVolumeGeometryGenerator::CPU_SILHOUETTE) { ref_ptr< Drawable > caps; caps = _svgg.getCapsGeometry(); caps->setUseDisplayList( false ); ref_ptr< Geode > geode_caps = new Geode; geode_caps->addDrawable( caps ); cv.pushStateSet( _ss23_caps ); geode_caps->accept( cv ); cv.popStateSet(); } else if( _svgg.getMode() == ShadowVolumeGeometryGenerator::GPU_RAW || _svgg.getMode() == ShadowVolumeGeometryGenerator::GPU_SILHOUETTE) { cv.pushStateSet( _ss23_caps ); geode->accept( cv ); cv.popStateSet(); } } } else{ ref_ptr< Drawable > d = _svgg.createGeometry(); d->setUseDisplayList( false ); ref_ptr< Geode > geode = new Geode; geode->addDrawable( d ); cv.pushStateSet( _ss2 ); geode->accept( cv ); cv.popStateSet(); // pass 3 cv.pushStateSet( _ss3 ); geode->accept( cv ); cv.popStateSet(); if(_svgg.getMethod() == ShadowVolumeGeometryGenerator::ZFAIL){ if( _svgg.getMode() == ShadowVolumeGeometryGenerator::CPU_RAW || _svgg.getMode() == ShadowVolumeGeometryGenerator::CPU_SILHOUETTE) { ref_ptr< Drawable > caps; ref_ptr< Geode > geode_caps = new Geode; caps = _svgg.getCapsGeometry(); caps->setUseDisplayList( false ); geode_caps->addDrawable( caps ); cv.pushStateSet( _ss2_caps ); geode_caps->accept( cv ); cv.popStateSet(); cv.pushStateSet( _ss3_caps ); geode_caps->accept( cv ); cv.popStateSet(); } else if( _svgg.getMode() == ShadowVolumeGeometryGenerator::GPU_RAW || _svgg.getMode() == ShadowVolumeGeometryGenerator::GPU_SILHOUETTE) { //_just_caps->set(1); cv.pushStateSet( _ss2_caps ); geode->accept( cv ); cv.popStateSet(); cv.pushStateSet( _ss3_caps ); geode->accept( cv ); cv.popStateSet(); //_just_caps->set(0); } } } //notify(NOTICE)<<"CULL END!!!"<<std::endl; }
void ShadowVolume::cull(osgUtil::CullVisitor& cv) { osg::ref_ptr<osgUtil::RenderBin> original_bin = cv.getCurrentRenderBin(); osg::ref_ptr<osgUtil::RenderBin> new_bin = original_bin->find_or_insert(0,"RenderBin"); cv.setCurrentRenderBin(new_bin.get()); _shadowedScene->osg::Group::traverse(cv); cv.setCurrentRenderBin(original_bin.get()); osgUtil::RenderBin::RenderBinList::iterator itr = new_bin->getRenderBinList().find(1000); osg::ref_ptr<osgUtil::RenderBin> shadowVolumeBin; if (itr != new_bin->getRenderBinList().end()) { shadowVolumeBin = itr->second; if (shadowVolumeBin.valid()) { //OSG_NOTICE<<"Found shadow volume bin, now removing it"<<std::endl; new_bin->getRenderBinList().erase(itr); } } if (shadowVolumeBin.valid()) { original_bin->setStateSet(_ss1.get()); osgUtil::RenderStage* orig_rs = cv.getRenderStage(); osgUtil::RenderStage* new_rs = new osgUtil::RenderStage; orig_rs->addPostRenderStage(new_rs); new_rs->setViewport(orig_rs->getViewport()); new_rs->setClearColor(orig_rs->getClearColor()); new_rs->setClearMask(GL_STENCIL_BUFFER_BIT); new_rs->setDrawBuffer(orig_rs->getDrawBuffer(), orig_rs->getDrawBufferApplyMask()); new_rs->setReadBuffer(orig_rs->getReadBuffer(), orig_rs->getReadBufferApplyMask()); new_rs->setColorMask(orig_rs->getColorMask()); osg::Vec4 lightpos; osg::ref_ptr<osgUtil::PositionalStateContainer> ps = new osgUtil::PositionalStateContainer; new_rs->setPositionalStateContainer(ps.get()); const osg::Light* selectLight = 0; osgUtil::PositionalStateContainer::AttrMatrixList& aml = orig_rs->getPositionalStateContainer()->getAttrMatrixList(); for(osgUtil::PositionalStateContainer::AttrMatrixList::iterator itr = aml.begin(); itr != aml.end(); ++itr) { const osg::Light* light = dynamic_cast<const osg::Light*>(itr->first.get()); if (light) { osg::RefMatrix* matrix = itr->second.get(); if (matrix) lightpos = light->getPosition() * (*matrix); else lightpos = light->getPosition(); selectLight = light; } else { ps->addPositionedAttribute(itr->second.get(), itr->first.get()); } } _ambientLight->setPosition(lightpos); orig_rs->addPositionedAttribute(0,_ambientLight.get()); _diffuseLight->setPosition(lightpos); if (selectLight) { _ambientLight->setAmbient(selectLight->getAmbient()); _diffuseLight->setDiffuse(selectLight->getDiffuse()); _diffuseLight->setSpecular(selectLight->getSpecular()); _diffuseLight->setDirection(selectLight->getDirection()); _diffuseLight->setConstantAttenuation(selectLight->getConstantAttenuation()); _diffuseLight->setLinearAttenuation(selectLight->getLinearAttenuation()); _diffuseLight->setQuadraticAttenuation(selectLight->getQuadraticAttenuation()); _diffuseLight->setSpotExponent(selectLight->getSpotExponent()); _diffuseLight->setSpotCutoff(selectLight->getSpotCutoff()); } ps->addPositionedAttribute(0, _diffuseLight.get()); if (_lightpos != lightpos && _dynamicShadowVolumes) { _lightpos = lightpos; osg::Matrix eyeToWorld; eyeToWorld.invert(*cv.getModelViewMatrix()); _occluder->computeShadowVolumeGeometry(lightpos * eyeToWorld, *_shadowVolume); } if (shadowVolumeBin.valid()) { // new_rs->setStateSet(_mainShadowStateSet.get()); new_rs->getRenderBinList()[0] = shadowVolumeBin; shadowVolumeBin->setStateSet(_shadowVolumeStateSet.get()); osg::ref_ptr<osgUtil::RenderBin> nested_bin = new_rs->find_or_insert(1,"RenderBin"); nested_bin->getRenderBinList()[0] = new_bin; nested_bin->setStateSet(_shadowedSceneStateSet.get()); } } }
bool GraticuleLabelingEngine::cullTraverse(osgUtil::CullVisitor& nv, CameraData& data) { osg::Camera* cam = nv.getCurrentCamera(); // Don't draw the labels if we are too far from North-Up: double heading = getCameraHeading(cam->getViewMatrix()); if (osg::RadiansToDegrees(fabs(heading)) > 7.0) return false; // Initialize the label pool for this camera if we have not done so: if (data.xLabels.empty()) { for (unsigned i = 0; i < MAX_LABELS; ++i) { LabelNode* label = new LabelNode(); label->setDynamic(true); label->setStyle(_xLabelStyle); label->setHorizonCulling(false); label->setOcclusionCulling(false); data.xLabels.push_back(label); } for (unsigned i = 0; i < MAX_LABELS; ++i) { LabelNode* label = new LabelNode(); label->setDynamic(true); label->setStyle(_yLabelStyle); label->setHorizonCulling(false); label->setOcclusionCulling(false); data.yLabels.push_back(label); } } // Start out with all labels off. We will then turn back on the ones we use: for (unsigned i = 0; i < MAX_LABELS; ++i) { data.xLabels[i]->setNodeMask(0); data.yLabels[i]->setNodeMask(0); } // Intersect the corners of the view frustum with the ellipsoid. // This will yield the approximate geo-extent of the view. // TODO: graduate this to the core if generally useful - could be helpful // for displaying the extent of the current view. // Calculate the "clip to world" matrix = MVPinv. osg::Matrix MVP = (*nv.getModelViewMatrix()) * cam->getProjectionMatrix(); osg::Matrix MVPinv; MVPinv.invert(MVP); EllipsoidIntersector ellipsoid(_srs->getEllipsoid()); // For each corner, transform the clip coordinates at the near and far // planes into world space and intersect that line with the ellipsoid: osg::Vec3d p0, p1; // find the lower-left corner of the frustum: osg::Vec3d LL_world; p0 = osg::Vec3d(-1, -1, -1) * MVPinv; p1 = osg::Vec3d(-1, -1, +1) * MVPinv; bool LL_ok = ellipsoid.intersectLine(p0, p1, LL_world); if (!LL_ok) return false; // find the upper-left corner of the frustum: osg::Vec3d UL_world; p0 = osg::Vec3d(-1, +1, -1) * MVPinv; p1 = osg::Vec3d(-1, +1, +1) * MVPinv; bool UL_ok = ellipsoid.intersectLine(p0, p1, UL_world); if (!UL_ok) return false; // find the lower-right corner of the frustum: osg::Vec3d LR_world; p0 = osg::Vec3d(+1, -1, -1) * MVPinv; p1 = osg::Vec3d(+1, -1, +1) * MVPinv; bool LR_ok = ellipsoid.intersectLine(p0, p1, LR_world); if (!LR_ok) return false; // Use this for clamping geopoints to the edges of the frustum: ClipSpace window(MVP, MVPinv); return updateLabels(LL_world, UL_world, LR_world, window, data); }