void SimpleDotVisitor::handle(osg::Drawable &drawable, int id) { std::stringstream label; label << "<top> " << drawable.className(); if (!drawable.getName().empty()) { label << "| " << drawable.getName(); } drawNode(id, "record", "solid", label.str(), "blue", "white"); }
void apply(osg::Drawable& geom) { if (_hardware) { osgAnimation::RigGeometry* rig = dynamic_cast<osgAnimation::RigGeometry*>(&geom); if (rig) rig->setRigTransformImplementation(new MyRigTransformHardware); } #if 0 if (geom.getName() != std::string("BoundingBox")) // we disable compute of bounding box for all geometry except our bounding box geom.setComputeBoundingBoxCallback(new osg::Drawable::ComputeBoundingBoxCallback); // geom.setInitialBound(new osg::Drawable::ComputeBoundingBoxCallback); #endif }
void GLObjectsVisitor::apply(osg::Drawable& drawable) { if (_drawablesAppliedSet.count(&drawable)!=0) return; if (_checkGLErrors==osg::State::ONCE_PER_ATTRIBUTE) _renderInfo.getState()->checkGLErrors("start of Drawable::apply(osg::Drawable& drawable)"); _drawablesAppliedSet.insert(&drawable); if (drawable.getStateSet()) { apply(*(drawable.getStateSet())); } if (_mode&SWITCH_OFF_DISPLAY_LISTS) { drawable.setUseDisplayList(false); } if (_mode&SWITCH_ON_DISPLAY_LISTS) { drawable.setUseDisplayList(true); } if (_mode&SWITCH_ON_VERTEX_BUFFER_OBJECTS) { drawable.setUseVertexBufferObjects(true); } if (_mode&SWITCH_OFF_VERTEX_BUFFER_OBJECTS) { drawable.setUseVertexBufferObjects(false); } if (_mode&COMPILE_DISPLAY_LISTS && _renderInfo.getState() && (drawable.getUseDisplayList() || drawable.getUseVertexBufferObjects())) { drawable.compileGLObjects(_renderInfo); if (_checkGLErrors==osg::State::ONCE_PER_ATTRIBUTE) _renderInfo.getState()->checkGLErrors("after drawable.compileGLObjects() call in Drawable::apply(osg::Drawable& drawable) "); } if (_mode&RELEASE_DISPLAY_LISTS) { drawable.releaseGLObjects(_renderInfo.getState()); } }
void VertexCacheOptimizer::apply(osg::Drawable& drawable) { if (drawable.getDataVariance() == osg::Object::DYNAMIC) return; osg::Geometry* geom = drawable.asGeometry(); if ( geom ) { if ( geom->getDataVariance() == osg::Object::DYNAMIC ) return; // vertex cache optimizations currently only support surface geometries. // all or nothing in the geode. osg::Geometry::PrimitiveSetList& psets = geom->getPrimitiveSetList(); for( osg::Geometry::PrimitiveSetList::iterator i = psets.begin(); i != psets.end(); ++i ) { switch( (*i)->getMode() ) { case GL_TRIANGLES: case GL_TRIANGLE_FAN: case GL_TRIANGLE_STRIP: case GL_QUADS: case GL_QUAD_STRIP: case GL_POLYGON: break; default: return; } } } //OE_NOTICE << LC << "VC optimizing..." << std::endl; // passed the test; run the optimizer. osgUtil::VertexCacheVisitor vcv; drawable.accept( vcv ); vcv.optimizeVertices(); osgUtil::VertexAccessOrderVisitor vaov; drawable.accept( vaov ); vaov.optimizeOrder(); traverse( drawable ); }
// decompose Drawable primitives into triangles, print out these triangles and computed normals. void printTriangles(const std::string& name, osg::Drawable& drawable) { std::cout<<name<<std::endl; osg::TriangleFunctor<NormalPrint> tf; drawable.accept(tf); std::cout<<std::endl; }
void GLObjectsVisitor::apply(osg::Drawable& drawable) { if (_drawablesAppliedSet.count(&drawable)!=0) return; _drawablesAppliedSet.insert(&drawable); if (_mode&SWITCH_OFF_DISPLAY_LISTS) { drawable.setUseDisplayList(false); } if (_mode&SWITCH_ON_DISPLAY_LISTS) { drawable.setUseDisplayList(true); } if (_mode&SWITCH_ON_VERTEX_BUFFER_OBJECTS) { drawable.setUseVertexBufferObjects(true); } if (_mode&SWITCH_OFF_VERTEX_BUFFER_OBJECTS) { drawable.setUseVertexBufferObjects(false); } if (_mode&COMPILE_DISPLAY_LISTS && _renderInfo.getState() && (drawable.getUseDisplayList() || drawable.getUseVertexBufferObjects())) { drawable.compileGLObjects(_renderInfo); } if (_mode&RELEASE_DISPLAY_LISTS) { drawable.releaseGLObjects(_renderInfo.getState()); } if (drawable.getStateSet()) { apply(*(drawable.getStateSet())); } }
CullVisitor::value_type CullVisitor::computeNearestPointInFrustum(const osg::Matrix& matrix, const osg::Polytope::PlaneList& planes,const osg::Drawable& drawable) { // OSG_WARN<<"CullVisitor::computeNearestPointInFrustum("<<getTraversalNumber()<<"\t"<<planes.size()<<std::endl; osg::TriangleFunctor<ComputeNearestPointFunctor> cnpf; cnpf.set(_computed_znear, matrix, &planes); drawable.accept(cnpf); return cnpf._znear; }
virtual void apply(osg::Drawable &drawable) { if (!mTriangleMesh) mTriangleMesh.reset(new btTriangleMesh); osg::Matrixf worldMat = osg::computeLocalToWorld(getNodePath()); osg::TriangleFunctor<GetTriangleFunctor> functor; functor.setTriMesh(mTriangleMesh.get()); functor.setMatrix(worldMat); drawable.accept(functor); }
void ShaderGenVisitor::apply(osg::Drawable &drawable) { osg::StateSet *stateSet = drawable.getStateSet(); if (stateSet) _state->pushStateSet(stateSet); update(&drawable); if (stateSet) _state->popStateSet(); }
void StatsVisitor::apply(osg::Drawable& drawable) { if (drawable.getStateSet()) { ++_numInstancedStateSet; _statesetSet.insert(drawable.getStateSet()); } ++_numInstancedDrawable; drawable.accept(_instancedStats); _drawableSet.insert(&drawable); osg::Geometry* geometry = dynamic_cast<osg::Geometry*>(&drawable); if (geometry) { ++_numInstancedGeometry; _geometrySet.insert(geometry); } }
void BuildTopologyVisitor::apply(osg::Drawable& drawable) { osg::Geometry* geom = drawable.asGeometry(); if (geom) { osg::Vec3Array* verts = dynamic_cast<osg::Vec3Array*>(geom->getVertexArray()); if (verts) { apply(&drawable, verts); } } }
void ShaderVisitor::apply(osg::Drawable& drawable) { // non-Geometry drawable (e.g. particle system) bool needPop = (drawable.getStateSet() != NULL); if (drawable.getStateSet()) { pushRequirements(); applyStateSet(drawable.getStateSet(), drawable); } if (!mRequirements.empty()) { const ShaderRequirements& reqs = mRequirements.back(); // TODO: find a better place for the stateset if (reqs.mShaderRequired || mForceShaders) createProgram(reqs, drawable); } if (needPop) popRequirements(); }
void AllocateAndMergeBufferObjectsVisitor::apply(osg::Drawable& drawable) { osg::Geometry* geom = drawable.asGeometry(); if ( geom ) { // We disable vbo's and then re-enable them to enable sharing of all the arrays. geom->setUseDisplayList( false ); geom->setUseVertexBufferObjects( false ); geom->setUseVertexBufferObjects( true ); } traverse(drawable); }
void StatsVisitor::apply(osg::Drawable& drawable) { if (drawable.getStateSet()) { apply(*drawable.getStateSet()); } ++_numInstancedDrawable; drawable.accept(_instancedStats); _drawableSet.insert(&drawable); osg::Geometry* geometry = drawable.asGeometry(); if (geometry) { ++_numInstancedGeometry; _geometrySet.insert(geometry); ++_numInstancedFastGeometry; _fastGeometrySet.insert(geometry); } }
bool CullVisitor::updateCalculatedNearFar(const osg::Matrix& matrix,const osg::Drawable& drawable, bool isBillboard) { const osg::BoundingBox& bb = drawable.getBound(); value_type d_near, d_far; if (isBillboard) { #ifdef TIME_BILLBOARD_NEAR_FAR_CALCULATION static unsigned int lastFrameNumber = getTraversalNumber(); static unsigned int numBillboards = 0; static double elapsed_time = 0.0; if (lastFrameNumber != getTraversalNumber()) { OSG_NOTICE<<"Took "<<elapsed_time<<"ms to test "<<numBillboards<<" billboards"<<std::endl; numBillboards = 0; elapsed_time = 0.0; lastFrameNumber = getTraversalNumber(); } osg::Timer_t start_t = osg::Timer::instance()->tick(); #endif osg::Vec3 lookVector(-matrix(0,2),-matrix(1,2),-matrix(2,2)); unsigned int bbCornerFar = (lookVector.x()>=0?1:0) + (lookVector.y()>=0?2:0) + (lookVector.z()>=0?4:0); unsigned int bbCornerNear = (~bbCornerFar)&7; d_near = distance(bb.corner(bbCornerNear),matrix); d_far = distance(bb.corner(bbCornerFar),matrix); OSG_NOTICE.precision(15); if (false) { OSG_NOTICE<<"TESTING Billboard near/far computation"<<std::endl; // OSG_WARN<<"Checking corners of billboard "<<std::endl; // deprecated brute force way, use all corners of the bounding box. value_type nd_near, nd_far; nd_near = nd_far = distance(bb.corner(0),matrix); for(unsigned int i=0;i<8;++i) { value_type d = distance(bb.corner(i),matrix); if (d<nd_near) nd_near = d; if (d>nd_far) nd_far = d; OSG_NOTICE<<"\ti="<<i<<"\td="<<d<<std::endl; } if (nd_near==d_near && nd_far==d_far) { OSG_NOTICE<<"\tBillboard near/far computation correct "<<std::endl; } else { OSG_NOTICE<<"\tBillboard near/far computation ERROR\n\t\t"<<d_near<<"\t"<<nd_near <<"\n\t\t"<<d_far<<"\t"<<nd_far<<std::endl; } } #ifdef TIME_BILLBOARD_NEAR_FAR_CALCULATION osg::Timer_t end_t = osg::Timer::instance()->tick(); elapsed_time += osg::Timer::instance()->delta_m(start_t,end_t); ++numBillboards; #endif } else { // efficient computation of near and far, only taking into account the nearest and furthest // corners of the bounding box. d_near = distance(bb.corner(_bbCornerNear),matrix); d_far = distance(bb.corner(_bbCornerFar),matrix); } if (d_near>d_far) { std::swap(d_near,d_far); if ( !EQUAL_F(d_near, d_far) ) { OSG_WARN<<"Warning: CullVisitor::updateCalculatedNearFar(.) near>far in range calculation,"<< std::endl; OSG_WARN<<" correcting by swapping values d_near="<<d_near<<" dfar="<<d_far<< std::endl; } } if (d_far<0.0) { // whole object behind the eye point so discard return false; } if (d_near<_computed_znear) { if (_computeNearFar==COMPUTE_NEAR_FAR_USING_PRIMITIVES) { osg::Polytope& frustum = getCurrentCullingSet().getFrustum(); if (frustum.getResultMask()) { if (isBillboard) { // OSG_WARN<<"Adding billboard into deffered list"<<std::endl; osg::Polytope transformed_frustum; transformed_frustum.setAndTransformProvidingInverse(getProjectionCullingStack().back().getFrustum(),matrix); // insert drawable into the deferred list of drawables which will be handled at the popProjectionMatrix(). _nearPlaneCandidateMap.insert( DistanceMatrixDrawableMap::value_type(d_near,MatrixPlanesDrawables(matrix,&drawable,transformed_frustum)) ); } else { // insert drawable into the deferred list of drawables which will be handled at the popProjectionMatrix(). _nearPlaneCandidateMap.insert( DistanceMatrixDrawableMap::value_type(d_near,MatrixPlanesDrawables(matrix,&drawable,frustum)) ); } // use the far point if its nearer than current znear as this is a conservative estimate of the znear // while the final computation for this drawable is deferred. if (d_far<_computed_znear) { if (d_far>=0.0) _computed_znear = d_far; else OSG_WARN<<" 1) sett near with dnear="<<d_near<<" dfar="<<d_far<< std::endl; } } else { if (d_near>=0.0) _computed_znear = d_near; else OSG_WARN<<" 2) sett near with d_near="<<d_near<< std::endl; } } else { //if (d_near<0.0) OSG_WARN<<" 3) set near with d_near="<<d_near<< std::endl; _computed_znear = d_near; } } if (d_far>_computed_zfar) _computed_zfar = d_far; /* // deprecated brute force way, use all corners of the bounding box. updateCalculatedNearFar(bb.corner(0)); updateCalculatedNearFar(bb.corner(1)); updateCalculatedNearFar(bb.corner(2)); updateCalculatedNearFar(bb.corner(3)); updateCalculatedNearFar(bb.corner(4)); updateCalculatedNearFar(bb.corner(5)); updateCalculatedNearFar(bb.corner(6)); updateCalculatedNearFar(bb.corner(7)); */ return true; }
void osgManipulator::setDrawableToAlwaysCull(osg::Drawable& drawable) { ForceCullCallback* cullCB = new ForceCullCallback; drawable.setCullCallback (cullCB); }
void GeometryClamper::apply(osg::Drawable& drawable) { if ( !_terrainSRS.valid() ) return; osg::Geometry* geom = drawable.asGeometry(); if ( !geom ) return; const osg::Matrixd& local2world = _matrixStack.back(); osg::Matrix world2local; world2local.invert( local2world ); const osg::EllipsoidModel* em = _terrainSRS->getEllipsoid(); osg::Vec3d n_vector(0,0,1), start, end, msl; bool isGeocentric = _terrainSRS->isGeographic(); osgUtil::IntersectionVisitor iv( _lsi.get() ); double r = std::min( em->getRadiusEquator(), em->getRadiusPolar() ); unsigned count = 0; bool geomDirty = false; osg::Vec3Array* verts = static_cast<osg::Vec3Array*>(geom->getVertexArray()); osg::FloatArray* zOffsets = 0L; // if preserve-Z is on, check for our elevations array. Create it if is doesn't // already exist. bool buildZOffsets = false; if ( _preserveZ ) { osg::UserDataContainer* udc = geom->getOrCreateUserDataContainer(); unsigned n = udc->getUserObjectIndex( ZOFFSETS_NAME ); if ( n < udc->getNumUserObjects() ) { zOffsets = dynamic_cast<osg::FloatArray*>(udc->getUserObject(n)); } else { zOffsets = new osg::FloatArray(); zOffsets->setName( ZOFFSETS_NAME ); zOffsets->reserve( verts->size() ); udc->addUserObject( zOffsets ); buildZOffsets = true; } } for( unsigned k=0; k<verts->size(); ++k ) { osg::Vec3d vw = (*verts)[k]; vw = vw * local2world; if ( isGeocentric ) { // normal to the ellipsoid: n_vector = em->computeLocalUpVector(vw.x(),vw.y(),vw.z()); // if we need to build to z-offsets array, calculate the z offset now: if ( buildZOffsets || _scale != 1.0 ) { double lat,lon,hae; em->convertXYZToLatLongHeight(vw.x(), vw.y(), vw.z(), lat, lon, hae); if ( buildZOffsets ) { zOffsets->push_back( (*verts)[k].z() ); } if ( _scale != 1.0 ) { msl = vw - n_vector*hae; } } } else if ( buildZOffsets ) // flat map { zOffsets->push_back( float(vw.z()) ); } _lsi->reset(); _lsi->setStart( vw + n_vector*r*_scale ); _lsi->setEnd( vw - n_vector*r ); _lsi->setIntersectionLimit( _lsi->LIMIT_NEAREST ); _terrainPatch->accept( iv ); if ( _lsi->containsIntersections() ) { osg::Vec3d fw = _lsi->getFirstIntersection().getWorldIntersectPoint(); if ( _scale != 1.0 ) { osg::Vec3d delta = fw - msl; fw += delta*_scale; } if ( _offset != 0.0 ) { fw += n_vector*_offset; } if ( _preserveZ && (zOffsets != 0L) ) { fw += n_vector * (*zOffsets)[k]; } (*verts)[k] = (fw * world2local); geomDirty = true; ++count; } } if ( geomDirty ) { geom->dirtyBound(); if ( geom->getUseVertexBufferObjects() ) { verts->getVertexBufferObject()->setUsage( GL_DYNAMIC_DRAW_ARB ); verts->dirty(); } else { geom->dirtyDisplayList(); } OE_DEBUG << LC << "clamped " << count << " verts." << std::endl; } }
void ProxyCullVisitor::apply(osg::Drawable& drawable) { if ( isCulledByProxyFrustum(drawable) ) return; _cv->pushOntoNodePath( &drawable ); // push the node's state. osg::StateSet* node_state = drawable.getStateSet(); if (node_state) _cv->pushStateSet(node_state); osg::RefMatrix& matrix = *_cv->getModelViewMatrix(); const osg::BoundingBox& bb = Utils::getBoundingBox(&drawable); bool culledOut = false; if( drawable.getCullCallback() ) { if (drawable.getCullCallback()->run(&drawable, _cv) == true) culledOut = true; } if (!culledOut) { if (drawable.isCullingActive() && isCulledByProxyFrustum(bb)) culledOut = true; } if ( !culledOut && _cv->getComputeNearFarMode() && bb.valid()) { if (!_cv->updateCalculatedNearFar(matrix,drawable,false)) culledOut = true; } if (!culledOut) { // need to track how push/pops there are, so we can unravel the stack correctly. unsigned int numPopStateSetRequired = 0; // push the geoset's state on the geostate stack. osg::StateSet* stateset = drawable.getStateSet(); if (stateset) { ++numPopStateSetRequired; _cv->pushStateSet(stateset); } osg::CullingSet& cs = _cv->getCurrentCullingSet(); if (!cs.getStateFrustumList().empty()) { osg::CullingSet::StateFrustumList& sfl = cs.getStateFrustumList(); for(osg::CullingSet::StateFrustumList::iterator itr = sfl.begin(); itr != sfl.end(); ++itr) { if (itr->second.contains(bb)) { ++numPopStateSetRequired; _cv->pushStateSet(itr->first.get()); } } } float depth = bb.valid() ? distance(bb.center(),matrix) : 0.0f; if (osg::isNaN(depth)) { for (osg::NodePath::const_iterator i = getNodePath().begin(); i != getNodePath().end(); ++i) { OSG_DEBUG << " \"" << (*i)->getName() << "\"" << std::endl; } } else { _cv->addDrawableAndDepth(&drawable,&matrix,depth); } for(unsigned int i=0;i< numPopStateSetRequired; ++i) { _cv->popStateSet(); } } // pop the node's state off the geostate stack. if (node_state) _cv->popStateSet(); _cv->popFromNodePath(); }
void SetDataVarianceVisitor::apply(osg::Drawable& drawable) { drawable.setDataVariance(_value); traverse(drawable); }