void RayTracedTechnique::traverse(osg::NodeVisitor& nv) { // OSG_NOTICE<<"RayTracedTechnique::traverse(osg::NodeVisitor& nv)"<<std::endl; if (!_volumeTile) return; // if app traversal update the frame count. if (nv.getVisitorType()==osg::NodeVisitor::UPDATE_VISITOR) { if (_volumeTile->getDirty()) _volumeTile->init(); osgUtil::UpdateVisitor* uv = nv.asUpdateVisitor(); if (uv) { update(uv); return; } } else if (nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR) { osgUtil::CullVisitor* cv = nv.asCullVisitor(); if (cv) { cull(cv); return; } } if (_volumeTile->getDirty()) { OSG_INFO<<"******* Doing init ***********"<<std::endl; _volumeTile->init(); } }
void Technique::traverse_implementation(osg::NodeVisitor& nv, Effect* fx) { // define passes if necessary if (_passes.empty()) { define_passes(); } // special actions must be taken if the node visitor is actually a CullVisitor osgUtil::CullVisitor* cv = nv.asCullVisitor(); if (cv) { // traverse all passes for (int i=0; i<getNumPasses(); ++i) { // push the i-th pass' StateSet cv->pushStateSet(_passes[i].get()); // traverse the override node if defined, otherwise // traverse children as a Group would do osg::Node *override = getOverrideChild(i); if (override) { override->accept(nv); } else { fx->inherited_traverse(nv); } // pop the StateSet cv->popStateSet(); }
void TXPNode::traverse(osg::NodeVisitor& nv) { switch(nv.getVisitorType()) { case osg::NodeVisitor::CULL_VISITOR: { OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex); osgUtil::CullVisitor* cv = nv.asCullVisitor(); if (cv) { //#define PRINT_TILEMAPP_TIMEINFO #ifdef PRINT_TILEMAPP_TIMEINFO const osg::Timer& timer = *osg::Timer::instance(); osg::Timer_t start = timer.tick(); std::cout<<"Doing visible tile search"<<std::endl; #endif // PRINT_TILEMAPP_TIMEINFO osg::ref_ptr<TileMapper> tileMapper = new TileMapper; tileMapper->setLODScale(cv->getLODScale()); tileMapper->pushReferenceViewPoint(cv->getReferenceViewPoint()); tileMapper->pushViewport(cv->getViewport()); tileMapper->pushProjectionMatrix((cv->getProjectionMatrix())); tileMapper->pushModelViewMatrix((cv->getModelViewMatrix()), osg::Transform::RELATIVE_RF); // traverse the scene graph to search for valid tiles accept(*tileMapper); tileMapper->popModelViewMatrix(); tileMapper->popProjectionMatrix(); tileMapper->popViewport(); tileMapper->popReferenceViewPoint(); //std::cout<<" found " << tileMapper._tileMap.size() << std::endl; cv->setUserData(tileMapper.get()); #ifdef PRINT_TILEMAPP_TIMEINFO std::cout<<"Completed visible tile search in "<<timer.delta_m(start,timer.tick())<<std::endl; #endif // PRINT_TILEMAPP_TIMEINFO } updateEye(nv); break; } case osg::NodeVisitor::UPDATE_VISITOR: { OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex); updateSceneGraph(); break; } default: break; } Group::traverse(nv); }
void osgParticle::ParticleSystemUpdater::traverse(osg::NodeVisitor& nv) { osgUtil::CullVisitor* cv = nv.asCullVisitor(); if (cv) { if (nv.getFrameStamp()) { if( _frameNumber < nv.getFrameStamp()->getFrameNumber()) { _frameNumber = nv.getFrameStamp()->getFrameNumber(); double t = nv.getFrameStamp()->getSimulationTime(); if (_t0 != -1.0) { ParticleSystem_Vector::iterator i; for (i=_psv.begin(); i!=_psv.end(); ++i) { ParticleSystem* ps = i->get(); ParticleSystem::ScopedWriteLock lock(*(ps->getReadWriteMutex())); // We need to allow at least 2 frames difference, because the particle system's lastFrameNumber // is updated in the draw thread which may not have completed yet. if (!ps->isFrozen() && (!ps->getFreezeOnCull() || ((nv.getFrameStamp()->getFrameNumber()-ps->getLastFrameNumber()) <= 2)) ) { ps->update(t - _t0, nv); } } } _t0 = t; } } else { OSG_WARN << "osgParticle::ParticleSystemUpdater::traverse(NodeVisitor&) requires a valid FrameStamp to function, particles not updated.\n"; } } Node::traverse(nv); }
void ShadowTechnique::traverse(osg::NodeVisitor& nv) { if (!_shadowedScene) return; if (nv.getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR) { if (_dirty) init(); update(nv); } else if (nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR) { osgUtil::CullVisitor* cv = nv.asCullVisitor(); if (cv) cull(*cv); else _shadowedScene->osg::Group::traverse(nv); } else { _shadowedScene->osg::Group::traverse(nv); } }
void osgParticle::ParticleSystemUpdater::traverse(osg::NodeVisitor& nv) { osgUtil::CullVisitor* cv = nv.asCullVisitor(); if (cv) { if (nv.getFrameStamp()) { if( _frameNumber < nv.getFrameStamp()->getFrameNumber()) { _frameNumber = nv.getFrameStamp()->getFrameNumber(); double t = nv.getFrameStamp()->getSimulationTime(); if (_t0 != -1.0) { ParticleSystem_Vector::iterator i; for (i=_psv.begin(); i!=_psv.end(); ++i) { ParticleSystem* ps = i->get(); ParticleSystem::ScopedWriteLock lock(*(ps->getReadWriteMutex())); if (!ps->isFrozen() && (ps->getLastFrameNumber() >= (nv.getFrameStamp()->getFrameNumber() - 1) || !ps->getFreezeOnCull())) { ps->update(t - _t0, nv); } } } _t0 = t; } } else { OSG_WARN << "osgParticle::ParticleSystemUpdater::traverse(NodeVisitor&) requires a valid FrameStamp to function, particles not updated.\n"; } } Node::traverse(nv); }
void osgParticle::ParticleProcessor::traverse(osg::NodeVisitor& nv) { // typecast the NodeVisitor to CullVisitor osgUtil::CullVisitor* cv = nv.asCullVisitor(); // continue only if the visitor actually is a cull visitor if (cv) { // continue only if the particle system is valid if (_ps.valid()) { if (nv.getFrameStamp()) { ParticleSystem::ScopedWriteLock lock(*(_ps->getReadWriteMutex())); //added- 1/17/06- [email protected] //a check to make sure we havent updated yet this frame if(_frameNumber < nv.getFrameStamp()->getFrameNumber()) { // retrieve the current time double t = nv.getFrameStamp()->getSimulationTime(); // reset this processor if we've reached the reset point if ((_currentTime >= _resetTime) && (_resetTime > 0)) { _currentTime = 0; _t0 = -1; } // skip if we haven't initialized _t0 yet if (_t0 != -1) { // check whether the processor is alive bool alive = false; if (_currentTime >= _startTime) { if (_endless || (_currentTime < (_startTime + _lifeTime))) alive = true; } // update current time _currentTime += t - _t0; // process only if the particle system is not frozen/culled // We need to allow at least 2 frames difference, because the particle system's lastFrameNumber // is updated in the draw thread which may not have completed yet. if (alive && _enabled && !_ps->isFrozen() && (!_ps->getFreezeOnCull() || ((nv.getFrameStamp()->getFrameNumber()-_ps->getLastFrameNumber()) <= 2)) ) { // initialize matrix flags _need_ltw_matrix = true; _need_wtl_matrix = true; _current_nodevisitor = &nv; // do some process (unimplemented in this base class) process( t - _t0 ); } else { //The values of _previous_wtl_matrix and _previous_ltw_matrix will be invalid //since processing was skipped for this frame _first_ltw_compute = true; _first_wtl_compute = true; } } _t0 = t; } //added- 1/17/06- [email protected] //updates the _frameNumber, keeping it current _frameNumber = nv.getFrameStamp()->getFrameNumber(); } else { OSG_WARN << "osgParticle::ParticleProcessor::traverse(NodeVisitor&) requires a valid FrameStamp to function, particles not updated.\n"; } } else { OSG_WARN << "ParticleProcessor \"" << getName() << "\": invalid particle system\n"; } } // call the inherited method Node::traverse(nv); }
void VolumeScene::traverse(osg::NodeVisitor& nv) { osgUtil::CullVisitor* cv = nv.asCullVisitor(); if (!cv) { Group::traverse(nv); return; } osg::ref_ptr<ViewData> viewData; bool initializeViewData = false; { OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_viewDataMapMutex); if (!_viewDataMap[cv]) { _viewDataMap[cv] = new ViewData; initializeViewData = true; } viewData = _viewDataMap[cv]; } if (initializeViewData) { OSG_NOTICE<<"Creating ViewData"<<std::endl; int textureWidth = 512; int textureHeight = 512; osg::Viewport* viewport = cv->getCurrentRenderStage()->getViewport(); if (viewport) { textureWidth = static_cast<int>(viewport->width()); textureHeight = static_cast<int>(viewport->height()); } // set up depth texture viewData->_depthTexture = new osg::Texture2D; viewData->_depthTexture->setTextureSize(textureWidth, textureHeight); viewData->_depthTexture->setInternalFormat(GL_DEPTH_COMPONENT); viewData->_depthTexture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR); viewData->_depthTexture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR); viewData->_depthTexture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_BORDER); viewData->_depthTexture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_BORDER); viewData->_depthTexture->setBorderColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); // set up color texture viewData->_colorTexture = new osg::Texture2D; viewData->_colorTexture->setTextureSize(textureWidth, textureHeight); viewData->_colorTexture->setInternalFormat(GL_RGBA); viewData->_colorTexture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR); viewData->_colorTexture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR); viewData->_colorTexture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_EDGE); viewData->_colorTexture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_EDGE); // set up the RTT Camera to capture the main scene to a color and depth texture that can be used in post processing viewData->_rttCamera = new osg::Camera; viewData->_rttCamera->setName("viewData->_rttCamera"); viewData->_rttCamera->attach(osg::Camera::DEPTH_BUFFER, viewData->_depthTexture.get()); viewData->_rttCamera->attach(osg::Camera::COLOR_BUFFER, viewData->_colorTexture.get()); viewData->_rttCamera->setCullCallback(new RTTCameraCullCallback(this)); viewData->_rttCamera->setViewport(0,0,textureWidth,textureHeight); // clear the depth and colour bufferson each clear. viewData->_rttCamera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); // set the camera to render before the main camera. viewData->_rttCamera->setRenderOrder(osg::Camera::PRE_RENDER); // tell the camera to use OpenGL frame buffer object where supported. viewData->_rttCamera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); viewData->_rttCamera->setReferenceFrame(osg::Transform::RELATIVE_RF); viewData->_rttCamera->setProjectionMatrix(osg::Matrixd::identity()); viewData->_rttCamera->setViewMatrix(osg::Matrixd::identity()); // create mesh for rendering the RTT textures onto the screen osg::ref_ptr<osg::Geode> geode = new osg::Geode; geode->setCullingActive(false); viewData->_backdropSubgraph = geode; //geode->addDrawable(osg::createTexturedQuadGeometry(osg::Vec3(-1.0f,-1.0f,-1.0f),osg::Vec3(2.0f,0.0f,-1.0f),osg::Vec3(0.0f,2.0f,-1.0f))); viewData->_geometry = new osg::Geometry; geode->addDrawable(viewData->_geometry.get()); viewData->_geometry->setUseDisplayList(false); viewData->_geometry->setUseVertexBufferObjects(false); viewData->_vertices = new osg::Vec3Array(4); viewData->_geometry->setVertexArray(viewData->_vertices.get()); osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array(1); (*colors)[0].set(1.0f,1.0f,1.0f,1.0f); viewData->_geometry->setColorArray(colors.get(), osg::Array::BIND_OVERALL); osg::ref_ptr<osg::Vec2Array> texcoords = new osg::Vec2Array(4); (*texcoords)[0].set(0.0f,1.0f); (*texcoords)[1].set(0.0f,0.0f); (*texcoords)[2].set(1.0f,1.0f); (*texcoords)[3].set(1.0f,0.0f); viewData->_geometry->setTexCoordArray(0, texcoords.get(), osg::Array::BIND_PER_VERTEX); viewData->_geometry->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLE_STRIP,0,4)); osg::ref_ptr<osg::StateSet> stateset = viewData->_geometry->getOrCreateStateSet(); stateset->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON); stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF); stateset->setMode(GL_BLEND, osg::StateAttribute::OFF); stateset->setMode(GL_ALPHA_TEST, osg::StateAttribute::OFF); stateset->setAttribute(new osg::Depth(osg::Depth::LEQUAL)); stateset->setRenderBinDetails(10,"DepthSortedBin"); osg::ref_ptr<osg::Program> program = new osg::Program; stateset->setAttribute(program.get()); // get vertex shaders from source osg::ref_ptr<osg::Shader> vertexShader = osgDB::readRefShaderFile(osg::Shader::VERTEX, "shaders/volume_color_depth.vert"); if (vertexShader.valid()) { program->addShader(vertexShader.get()); } #if 0 else { #include "Shaders/volume_color_depth_vert.cpp" program->addShader(new osg::Shader(osg::Shader::VERTEX, volume_color_depth_vert)); } #endif // get fragment shaders from source osg::ref_ptr<osg::Shader> fragmentShader = osgDB::readRefShaderFile(osg::Shader::FRAGMENT, "shaders/volume_color_depth.frag"); if (fragmentShader.valid()) { program->addShader(fragmentShader.get()); } #if 0 else { #include "Shaders/volume_color_depth_frag.cpp" program->addShader(new osg::Shader(osg::Shader::FRAGMENT, volume_color_depth_frag)); } #endif viewData->_stateset = new osg::StateSet; viewData->_stateset->addUniform(new osg::Uniform("colorTexture",0)); viewData->_stateset->addUniform(new osg::Uniform("depthTexture",1)); viewData->_stateset->setTextureAttributeAndModes(0, viewData->_colorTexture.get(), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE); viewData->_stateset->setTextureAttributeAndModes(1, viewData->_depthTexture.get(), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE); viewData->_viewportDimensionsUniform = new osg::Uniform("viewportDimensions",osg::Vec4(0.0,0.0,1280.0,1024.0)); viewData->_stateset->addUniform(viewData->_viewportDimensionsUniform.get()); geode->setStateSet(viewData->_stateset.get()); } else { // OSG_NOTICE<<"Reusing ViewData"<<std::endl; } osg::Matrix projectionMatrix = *(cv->getProjectionMatrix()); osg::Matrix modelviewMatrix = *(cv->getModelViewMatrix()); // new frame so need to clear last frames log of VolumeTiles viewData->clearTiles(); osg::Viewport* viewport = cv->getCurrentRenderStage()->getViewport(); if (viewport) { viewData->_viewportDimensionsUniform->set(osg::Vec4(viewport->x(), viewport->y(), viewport->width(),viewport->height())); int textureWidth = static_cast<int>(viewport->width()); int textureHeight = static_cast<int>(viewport->height()); if (textureWidth != viewData->_colorTexture->getTextureWidth() || textureHeight != viewData->_colorTexture->getTextureHeight()) { OSG_NOTICE<<"Need to change texture size to "<<textureWidth<<", "<< textureHeight<<std::endl; viewData->_colorTexture->setTextureSize(textureWidth, textureHeight); viewData->_colorTexture->dirtyTextureObject(); viewData->_depthTexture->setTextureSize(textureWidth, textureHeight); viewData->_depthTexture->dirtyTextureObject(); viewData->_rttCamera->setViewport(0, 0, textureWidth, textureHeight); if (viewData->_rttCamera->getRenderingCache()) { viewData->_rttCamera->getRenderingCache()->releaseGLObjects(0); } } } cv->setUserValue("VolumeSceneTraversal",std::string("RenderToTexture")); //OSG_NOTICE<<"Ready to traverse RTT Camera"<<std::endl; //OSG_NOTICE<<" RTT Camera ProjectionMatrix Before "<<viewData->_rttCamera->getProjectionMatrix()<<std::endl; viewData->_rttCamera->accept(nv); //OSG_NOTICE<<" RTT Camera ProjectionMatrix After "<<viewData->_rttCamera->getProjectionMatrix()<<std::endl; //OSG_NOTICE<<" cv ProjectionMatrix After "<<*(cv->getProjectionMatrix())<<std::endl; //OSG_NOTICE<<" after RTT near ="<<cv->getCalculatedNearPlane()<<std::endl; //OSG_NOTICE<<" after RTT far ="<<cv->getCalculatedFarPlane()<<std::endl; //OSG_NOTICE<<"tileVisited()"<<viewData->_tiles.size()<<std::endl; typedef osgUtil::CullVisitor::value_type NearFarValueType; NearFarValueType calculatedNearPlane = std::numeric_limits<NearFarValueType>::max(); NearFarValueType calculatedFarPlane = -std::numeric_limits<NearFarValueType>::max(); if (viewData->_rttCamera->getUserValue("CalculatedNearPlane",calculatedNearPlane) && viewData->_rttCamera->getUserValue("CalculatedFarPlane",calculatedFarPlane)) { calculatedNearPlane *= 0.5; calculatedFarPlane *= 2.0; //OSG_NOTICE<<"Got from RTTCamera CalculatedNearPlane="<<calculatedNearPlane<<std::endl; //OSG_NOTICE<<"Got from RTTCamera CalculatedFarPlane="<<calculatedFarPlane<<std::endl; if (calculatedNearPlane < cv->getCalculatedNearPlane()) cv->setCalculatedNearPlane(calculatedNearPlane); if (calculatedFarPlane > cv->getCalculatedFarPlane()) cv->setCalculatedFarPlane(calculatedFarPlane); } if (calculatedFarPlane>calculatedNearPlane) { cv->clampProjectionMatrix(projectionMatrix, calculatedNearPlane, calculatedFarPlane); } osg::Matrix inv_projectionModelViewMatrix; inv_projectionModelViewMatrix.invert(modelviewMatrix*projectionMatrix); double depth = 1.0; osg::Vec3d v00 = osg::Vec3d(-1.0,-1.0,depth)*inv_projectionModelViewMatrix; osg::Vec3d v01 = osg::Vec3d(-1.0,1.0,depth)*inv_projectionModelViewMatrix; osg::Vec3d v10 = osg::Vec3d(1.0,-1.0,depth)*inv_projectionModelViewMatrix; osg::Vec3d v11 = osg::Vec3d(1.0,1.0,depth)*inv_projectionModelViewMatrix; // OSG_NOTICE<<"v00= "<<v00<<std::endl; // OSG_NOTICE<<"v01= "<<v01<<std::endl; // OSG_NOTICE<<"v10= "<<v10<<std::endl; // OSG_NOTICE<<"v11= "<<v11<<std::endl; (*(viewData->_vertices))[0] = v01; (*(viewData->_vertices))[1] = v00; (*(viewData->_vertices))[2] = v11; (*(viewData->_vertices))[3] = v10; viewData->_geometry->dirtyBound(); //OSG_NOTICE<<" new after RTT near ="<<cv->getCalculatedNearPlane()<<std::endl; //OSG_NOTICE<<" new after RTT far ="<<cv->getCalculatedFarPlane()<<std::endl; viewData->_backdropSubgraph->accept(*cv); osg::NodePath nodePathPriorToTraversingSubgraph = cv->getNodePath(); cv->setUserValue("VolumeSceneTraversal",std::string("Post")); // for each tile that needs post rendering we need to add it into current RenderStage. Tiles& tiles = viewData->_tiles; for(Tiles::iterator itr = tiles.begin(); itr != tiles.end(); ++itr) { TileData* tileData = itr->second.get(); if (!tileData || !(tileData->active)) { OSG_INFO<<"Skipping TileData that is inactive : "<<tileData<<std::endl; continue; } unsigned int numStateSetPushed = 0; // OSG_NOTICE<<"VolumeTile to add "<<tileData->projectionMatrix.get()<<", "<<tileData->modelviewMatrix.get()<<std::endl; osg::NodePath& nodePath = tileData->nodePath; cv->getNodePath() = nodePath; cv->pushProjectionMatrix(tileData->projectionMatrix.get()); cv->pushModelViewMatrix(tileData->modelviewMatrix.get(), osg::Transform::ABSOLUTE_RF_INHERIT_VIEWPOINT); cv->pushStateSet(viewData->_stateset.get()); ++numStateSetPushed; cv->pushStateSet(tileData->stateset.get()); ++numStateSetPushed; osg::NodePath::iterator np_itr = nodePath.begin(); // skip over all nodes above VolumeScene as this will have already been traversed by CullVisitor while(np_itr!=nodePath.end() && (*np_itr)!=viewData->_rttCamera.get()) { ++np_itr; } if (np_itr!=nodePath.end()) ++np_itr; // push the stateset on the nodes between this VolumeScene and the VolumeTile for(osg::NodePath::iterator ss_itr = np_itr; ss_itr != nodePath.end(); ++ss_itr) { if ((*ss_itr)->getStateSet()) { numStateSetPushed++; cv->pushStateSet((*ss_itr)->getStateSet()); // OSG_NOTICE<<" pushing StateSet"<<std::endl; } } cv->traverse(*(tileData->nodePath.back())); // pop the StateSet's for(unsigned int i=0; i<numStateSetPushed; ++i) { cv->popStateSet(); // OSG_NOTICE<<" popping StateSet"<<std::endl; } cv->popModelViewMatrix(); cv->popProjectionMatrix(); } // need to synchronize projection matrices: // current CV projection matrix // main scene RTT Camera projection matrix // each tile RTT Camera // each tile final render. cv->getNodePath() = nodePathPriorToTraversingSubgraph; }
void LightPointNode::traverse(osg::NodeVisitor& nv) { if (_lightPointList.empty()) { // no light points so no op. return; } //#define USE_TIMER #ifdef USE_TIMER osg::Timer timer; osg::Timer_t t1=0,t2=0,t3=0,t4=0,t5=0,t6=0,t7=0,t8=0; #endif #ifdef USE_TIMER t1 = timer.tick(); #endif osgUtil::CullVisitor* cv = nv.asCullVisitor(); #ifdef USE_TIMER t2 = timer.tick(); #endif // should we disable small feature culling here? if (cv /*&& !cv->isCulled(_bbox)*/) { osg::Matrix matrix = *(cv->getModelViewMatrix()); osg::RefMatrix& projection = *(cv->getProjectionMatrix()); osgUtil::StateGraph* rg = cv->getCurrentStateGraph(); if (rg->leaves_empty()) { // this is first leaf to be added to StateGraph // and therefore should not already know current render bin, // so need to add it. cv->getCurrentRenderBin()->addStateGraph(rg); } #ifdef USE_TIMER t3 = timer.tick(); #endif LightPointDrawable* drawable = NULL; osg::Referenced* object = rg->getUserData(); if (object) { if (typeid(*object)==typeid(LightPointDrawable)) { // resuse the user data attached to the render graph. drawable = static_cast<LightPointDrawable*>(object); } else if (typeid(*object)==typeid(LightPointSpriteDrawable)) { drawable = static_cast<LightPointSpriteDrawable*>(object); } else { // will need to replace UserData. OSG_WARN << "Warning: Replacing osgUtil::StateGraph::_userData to support osgSim::LightPointNode, may have undefined results."<<std::endl; } } if (!drawable) { drawable = _pointSprites ? new LightPointSpriteDrawable : new LightPointDrawable; rg->setUserData(drawable); if (cv->getFrameStamp()) { drawable->setSimulationTime(cv->getFrameStamp()->getSimulationTime()); } } // search for a drawable in the RenderLeaf list equal to the attached the one attached to StateGraph user data // as this will be our special light point drawable. osgUtil::StateGraph::LeafList::iterator litr; for(litr = rg->_leaves.begin(); litr != rg->_leaves.end() && (*litr)->_drawable.get()!=drawable; ++litr) {} if (litr == rg->_leaves.end()) { // haven't found the drawable added in the RenderLeaf list, therefore this may be the // first time through LightPointNode in this frame, so need to add drawable into the StateGraph RenderLeaf list // and update its time signatures. drawable->reset(); rg->addLeaf(new osgUtil::RenderLeaf(drawable,&projection,NULL,FLT_MAX)); // need to update the drawable's frame count. if (cv->getFrameStamp()) { drawable->updateSimulationTime(cv->getFrameStamp()->getSimulationTime()); } } #ifdef USE_TIMER t4 = timer.tick(); #endif #ifdef USE_TIMER t7 = timer.tick(); #endif if (cv->getComputeNearFarMode() != osgUtil::CullVisitor::DO_NOT_COMPUTE_NEAR_FAR) cv->updateCalculatedNearFar(matrix,_bbox); const float minimumIntensity = 1.0f/256.0f; const osg::Vec3 eyePoint = cv->getEyeLocal(); double time=drawable->getSimulationTime(); double timeInterval=drawable->getSimulationTimeInterval(); const osg::Polytope clipvol(cv->getCurrentCullingSet().getFrustum()); const bool computeClipping = false;//(clipvol.getCurrentMask()!=0); //LightPointDrawable::ColorPosition cp; for(LightPointList::iterator itr=_lightPointList.begin(); itr!=_lightPointList.end(); ++itr) { const LightPoint& lp = *itr; if (!lp._on) continue; const osg::Vec3& position = lp._position; // skip light point if it is not contianed in the view frustum. if (computeClipping && !clipvol.contains(position)) continue; // delta vector between eyepoint and light point. osg::Vec3 dv(eyePoint-position); float intensity = (_lightSystem.valid()) ? _lightSystem->getIntensity() : lp._intensity; // slip light point if its intensity is 0.0 or negative. if (intensity<=minimumIntensity) continue; // (SIB) Clip on distance, if close to limit, add transparancy float distanceFactor = 1.0f; if (_maxVisibleDistance2!=FLT_MAX) { if (dv.length2()>_maxVisibleDistance2) continue; else if (_maxVisibleDistance2 > 0) distanceFactor = 1.0f - osg::square(dv.length2() / _maxVisibleDistance2); } osg::Vec4 color = lp._color; // check the sector. if (lp._sector.valid()) { intensity *= (*lp._sector)(dv); // skip light point if it is intensity is 0.0 or negative. if (intensity<=minimumIntensity) continue; } // temporary accounting of intensity. //color *= intensity; // check the blink sequence. bool doBlink = lp._blinkSequence.valid(); if (doBlink && _lightSystem.valid()) doBlink = (_lightSystem->getAnimationState() == LightPointSystem::ANIMATION_ON); if (doBlink) { osg::Vec4 bs = lp._blinkSequence->color(time,timeInterval); color[0] *= bs[0]; color[1] *= bs[1]; color[2] *= bs[2]; color[3] *= bs[3]; } // if alpha value is less than the min intentsity then skip if (color[3]<=minimumIntensity) continue; float pixelSize = cv->pixelSize(position,lp._radius); // cout << "pixelsize = "<<pixelSize<<endl; // adjust pixel size to account for intensity. if (intensity!=1.0) pixelSize *= sqrt(intensity); // adjust alpha to account for max range (Fade on distance) color[3] *= distanceFactor; // round up to the minimum pixel size if required. float orgPixelSize = pixelSize; if (pixelSize<_minPixelSize) pixelSize = _minPixelSize; osg::Vec3 xpos(position*matrix); if (lp._blendingMode==LightPoint::BLENDED) { if (pixelSize<1.0f) { // need to use alpha blending... color[3] *= pixelSize; // color[3] *= osg::square(pixelSize); if (color[3]<=minimumIntensity) continue; drawable->addBlendedLightPoint(0, xpos,color); } else if (pixelSize<_maxPixelSize) { unsigned int lowerBoundPixelSize = (unsigned int)pixelSize; float remainder = osg::square(pixelSize-(float)lowerBoundPixelSize); // (SIB) Add transparency if pixel is clamped to minpixelsize if (orgPixelSize<_minPixelSize) color[3] *= (2.0/3.0) + (1.0/3.0) * sqrt(orgPixelSize / pixelSize); drawable->addBlendedLightPoint(lowerBoundPixelSize-1, xpos,color); color[3] *= remainder; drawable->addBlendedLightPoint(lowerBoundPixelSize, xpos,color); } else // use a billboard geometry. { drawable->addBlendedLightPoint((unsigned int)(_maxPixelSize-1.0), xpos,color); } } else // ADDITIVE blending. { if (pixelSize<1.0f) { // need to use alpha blending... color[3] *= pixelSize; // color[3] *= osg::square(pixelSize); if (color[3]<=minimumIntensity) continue; drawable->addAdditiveLightPoint(0, xpos,color); } else if (pixelSize<_maxPixelSize) { unsigned int lowerBoundPixelSize = (unsigned int)pixelSize; float remainder = osg::square(pixelSize-(float)lowerBoundPixelSize); // (SIB) Add transparency if pixel is clamped to minpixelsize if (orgPixelSize<_minPixelSize) color[3] *= (2.0/3.0) + (1.0/3.0) * sqrt(orgPixelSize / pixelSize); float alpha = color[3]; color[3] = alpha*(1.0f-remainder); drawable->addAdditiveLightPoint(lowerBoundPixelSize-1, xpos,color); color[3] = alpha*remainder; drawable->addAdditiveLightPoint(lowerBoundPixelSize, xpos,color); } else // use a billboard geometry. { drawable->addAdditiveLightPoint((unsigned int)(_maxPixelSize-1.0), xpos,color); } } } #ifdef USE_TIMER t8 = timer.tick(); #endif } #ifdef USE_TIMER cout << "compute"<<endl; cout << " t2-t1="<<t2-t1<<endl; cout << " t4-t3="<<t4-t3<<endl; cout << " t6-t5="<<t6-t5<<endl; cout << " t8-t7="<<t8-t7<<endl; cout << "_lightPointList.size()="<<_lightPointList.size()<<endl; cout << " t8-t7/size = "<<(float)(t8-t7)/(float)_lightPointList.size()<<endl; #endif }
void osgParticle::ParticleSystem::update(double dt, osg::NodeVisitor& nv) { // reset bounds _reset_bounds_flag = true; if (_useShaders) { // Update shader uniforms // This slightly reduces the consumption of traversing the particle vector, because we // don't compute tile and angle attributes that are useleff for shaders. // At present, our lcoal shader implementation will ignore these particle props: // _cur_tile, _s_coord, _t_coord, _prev_pos, _prev_angle and _angle osg::StateSet* stateset = getOrCreateStateSet(); if (_dirty_uniforms) { osg::Uniform* u_vd = stateset->getUniform("visibilityDistance"); if (u_vd) u_vd->set((float)_visibilityDistance); _dirty_uniforms = false; } } for(unsigned int i=0; i<_particles.size(); ++i) { Particle& particle = _particles[i]; if (particle.isAlive()) { if (particle.update(dt, _useShaders)) { update_bounds(particle.getPosition(), particle.getCurrentSize()); } else { reuseParticle(i); } } } if (_sortMode != NO_SORT) { // sort particles osgUtil::CullVisitor* cv = nv.asCullVisitor(); if (cv) { osg::Matrixd modelview = *(cv->getModelViewMatrix()); double scale = (_sortMode==SORT_FRONT_TO_BACK ? -1.0 : 1.0); double deadDistance = DBL_MAX; for (unsigned int i=0; i<_particles.size(); ++i) { Particle& particle = _particles[i]; if (particle.isAlive()) particle.setDepth(distance(particle.getPosition(), modelview) * scale); else particle.setDepth(deadDistance); } std::sort<Particle_vector::iterator>(_particles.begin(), _particles.end()); // Repopulate the death stack as it will have been invalidated by the sort. unsigned int numDead = _deadparts.size(); if (numDead>0) { // clear the death stack _deadparts = Death_stack(); // copy the tail of the _particles vector as this will contain all the dead Particle thanks to the depth sort against DBL_MAX Particle* first_dead_ptr = &_particles[_particles.size()-numDead]; Particle* last_dead_ptr = &_particles[_particles.size()-1]; for(Particle* dead_ptr = first_dead_ptr; dead_ptr<=last_dead_ptr; ++dead_ptr) { _deadparts.push(dead_ptr); } } } } // force recomputing of bounding box on next frame dirtyBound(); }
void Widget::traverseImplementation(osg::NodeVisitor& nv) { if (!_graphicsInitialized && nv.getVisitorType()!=osg::NodeVisitor::CULL_VISITOR) createGraphics(); osgGA::EventVisitor* ev = nv.asEventVisitor(); if (ev) { if (_visible && _enabled) { updateFocus(nv); // OSG_NOTICE<<"EventTraversal getHasEventFocus()="<<getHasEventFocus()<<std::endl; // signify that event has been taken by widget with focus bool widgetsWithFocusSetHandled = getHasEventFocus(); osgGA::EventQueue::Events& events = ev->getEvents(); for(osgGA::EventQueue::Events::iterator itr = events.begin(); itr != events.end(); ++itr) { if (handle(ev, itr->get()) || widgetsWithFocusSetHandled) { (*itr)->setHandled(true); ev->setEventHandled(true); } } GraphicsSubgraphMap::iterator itr = _graphicsSubgraphMap.begin(); while(itr!= _graphicsSubgraphMap.end() && itr->first<=0) { itr->second->accept(nv); ++itr; } osg::Group::traverse(nv); while(itr!= _graphicsSubgraphMap.end()) { itr->second->accept(nv); ++itr; } } } else if (_visible || (nv.getVisitorType()!=osg::NodeVisitor::UPDATE_VISITOR && nv.getVisitorType()!=osg::NodeVisitor::CULL_VISITOR && nv.getVisitorType()!=osg::NodeVisitor::INTERSECTION_VISITOR) ) { osgUtil::CullVisitor* cv = (nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR) ? nv.asCullVisitor() : 0; if (cv && _widgetStateSet.valid()) cv->pushStateSet(_widgetStateSet.get()); GraphicsSubgraphMap::iterator itr = _graphicsSubgraphMap.begin(); while(itr!= _graphicsSubgraphMap.end() && itr->first<=0) { itr->second->accept(nv); ++itr; } Group::traverse(nv); while(itr!= _graphicsSubgraphMap.end()) { itr->second->accept(nv); ++itr; } if (cv && _widgetStateSet.valid()) cv->popStateSet(); } }
void Impostor::traverse(osg::NodeVisitor& nv) { if (nv.getVisitorType() != osg::NodeVisitor::CULL_VISITOR) { LOD::traverse(nv); return; } osgUtil::CullVisitor* cv = nv.asCullVisitor(); if (!cv) { LOD::traverse(nv); return; } osg::Vec3 eyeLocal = nv.getEyePoint(); const BoundingSphere& bs = getBound(); unsigned int contextID = cv->getState() ? cv->getState()->getContextID() : 0; float distance2 = (eyeLocal-bs.center()).length2(); float LODScale = cv->getLODScale(); if (!cv->getImpostorsActive() || distance2*LODScale*LODScale<osg::square(getImpostorThreshold()) || distance2<bs.radius2()*2.0f) { // outwith the impostor distance threshold therefore simple // traverse the appropriate child of the LOD. LOD::traverse(nv); } else { // within the impostor distance threshold therefore attempt // to use impostor instead. RefMatrix& matrix = *cv->getModelViewMatrix(); // search for the best fit ImpostorSprite; ImpostorSprite* impostorSprite = findBestImpostorSprite(contextID,eyeLocal); if (impostorSprite) { // impostor found, now check to see if it is good enough to use float error = impostorSprite->calcPixelError(*(cv->getMVPW())); if (error>cv->getImpostorPixelErrorThreshold()) { // chosen impostor sprite pixel error is too great to use // from this eye point, therefore invalidate it. impostorSprite=NULL; } } // need to think about sprite reuse and support for multiple context's. if (impostorSprite==NULL) { // no appropriate sprite has been found therefore need to create // one for use // create the impostor sprite. impostorSprite = createImpostorSprite(cv); //if (impostorSprite) impostorSprite->_color.set(0.0f,0.0f,1.0f,1.0f); } //else impostorSprite->_color.set(1.0f,1.0f,1.0f,1.0f); if (impostorSprite) { // update frame number to show that impostor is in action. impostorSprite->setLastFrameUsed(cv->getTraversalNumber()); if (cv->getComputeNearFarMode()) cv->updateCalculatedNearFar(matrix,*impostorSprite, false); StateSet* stateset = impostorSprite->getStateSet(); if (stateset) cv->pushStateSet(stateset); cv->addDrawableAndDepth(impostorSprite, &matrix, distance(getCenter(),matrix)); if (stateset) cv->popStateSet(); } else { // no impostor has been selected or created so default to // traversing the usual LOD selected child. LOD::traverse(nv); } } }