void ProjectVisitor::apply(osg::Geode& node) { if (_clearEveryDrawable) _projector.clear(); std::vector<osg::Drawable*> toremove; std::vector<osg::ref_ptr<osg::Geometry> > toadd; for (int i = 0; i < node.getNumDrawables(); i++) { osg::Timer_t t0 = osg::Timer::instance()->tick(); node.getDrawable(i)->accept(_projector); double duration = osg::Timer::instance()->delta_s(t0, osg::Timer::instance()->tick()); if (_projector.hasGeometry()) { toremove.push_back(node.getDrawable(i)); std::stringstream ss; ss << "projected_" << _index << ".osg"; osg::notify(osg::INFO) << "duration " << duration << " " << ss.str() << std::endl; if (_writeResultOnDisk) _projector.write(ss.str()); if (!_mergeGeometry) { osg::ref_ptr<osg::Geometry> result = _projector._result.get(); result->setUserData(node.getDrawable(i)->getUserData()); toadd.push_back(result); _projector.clear(); } } _index++; _cummulatedTime += duration; } if (_mergeGeometry) { if (_projector.hasGeometry()) { toadd.push_back(_projector._result.get()); } } for (int i = 0; i < toremove.size(); i++) // remove only where success to project data node.removeDrawable(toremove[i]); for (int i = 0; i < toadd.size(); i++) {// remove only where success to project data node.addDrawable(toadd[i]); } if (_projectToXYZ) { osg::ref_ptr<LatLongHeight2xyz> visitor = new LatLongHeight2xyz(); node.accept(*visitor); } // smooth after project if (_smooth) { osgUtil::SmoothingVisitor smooth; for (int i = 0; i < toadd.size(); i++) {// remove only where success to project data smooth.smooth(*toadd[i]); } } }
static bool readDrawables( osgDB::InputStream& is, osg::Geode& node ) { unsigned int size = 0; is >> size >> is.BEGIN_BRACKET; for ( unsigned int i=0; i<size; ++i ) { osg::ref_ptr<osg::Drawable> drawable = is.readObjectOfType<osg::Drawable>(); if ( drawable ) { node.addDrawable( drawable ); } } is >> is.END_BRACKET; return true; }
static bool readDrawables( osgDB::InputStream& is, osg::Geode& node ) { unsigned int size = 0; is >> size >> is.BEGIN_BRACKET; for ( unsigned int i=0; i<size; ++i ) { osg::Drawable* drawable = dynamic_cast<osg::Drawable*>( is.readObject() ); if ( drawable ) { node.addDrawable( drawable ); } } is >> is.END_BRACKET; return true; }
void apply( osg::Geode& geode ) { bool makeECEF = _cx.getSession()->getMapInfo().isGeocentric(); const SpatialReference* srs = _cx.profile()->getSRS(); NumericExpression scaleEx = *_symbol->scale(); osg::Matrixd scaleMatrix; // save the geode's drawables.. osg::Geode::DrawableList old_drawables = geode.getDrawableList(); // ..and clear out the drawables list. geode.removeDrawables( 0, geode.getNumDrawables() ); // foreach each drawable that was originally in the geode... for( osg::Geode::DrawableList::iterator i = old_drawables.begin(); i != old_drawables.end(); i++ ) { osg::Geometry* originalDrawable = dynamic_cast<osg::Geometry*>( i->get() ); if ( !originalDrawable ) continue; // go through the list of input features... for( FeatureList::const_iterator j = _features.begin(); j != _features.end(); j++ ) { const Feature* feature = j->get(); if ( _symbol->scale().isSet() ) { double scale = feature->eval( scaleEx, &_cx ); scaleMatrix.makeScale( scale, scale, scale ); } ConstGeometryIterator gi( feature->getGeometry(), false ); while( gi.hasMore() ) { const Geometry* geom = gi.next(); for( Geometry::const_iterator k = geom->begin(); k != geom->end(); ++k ) { osg::Vec3d point = *k; osg::Matrixd mat; if ( makeECEF ) { osg::Matrixd rotation; ECEF::transformAndGetRotationMatrix( point, srs, point, rotation ); mat = rotation * scaleMatrix * osg::Matrixd::translate(point) * _f2n->world2local(); } else { mat = scaleMatrix * osg::Matrixd::translate(point) * _f2n->world2local(); } // clone the source drawable once for each input feature. osg::ref_ptr<osg::Geometry> newDrawable = osg::clone( originalDrawable, osg::CopyOp::DEEP_COPY_ARRAYS | osg::CopyOp::DEEP_COPY_PRIMITIVES ); osg::Vec3Array* verts = dynamic_cast<osg::Vec3Array*>( newDrawable->getVertexArray() ); if ( verts ) { for( osg::Vec3Array::iterator v = verts->begin(); v != verts->end(); ++v ) { (*v).set( (*v) * mat ); } // add the new cloned, translated drawable back to the geode. geode.addDrawable( newDrawable.get() ); } } } } } geode.dirtyBound(); MeshConsolidator::run( geode ); // merge the geometry. Not sure this is necessary osgUtil::Optimizer opt; opt.optimize( &geode, osgUtil::Optimizer::MERGE_GEOMETRY | osgUtil::Optimizer::SHARE_DUPLICATE_STATE ); osg::NodeVisitor::apply( geode ); }
void apply( osg::Geode& geode ) { // save the geode's drawables.. osg::Geode::DrawableList old_drawables = geode.getDrawableList(); //OE_DEBUG << "ClusterVisitor geode " << &geode << " featureNode=" << _featureNode << " drawables=" << old_drawables.size() << std::endl; // ..and clear out the drawables list. geode.removeDrawables( 0, geode.getNumDrawables() ); // foreach each drawable that was originally in the geode... for( osg::Geode::DrawableList::iterator i = old_drawables.begin(); i != old_drawables.end(); i++ ) { osg::Geometry* originalDrawable = dynamic_cast<osg::Geometry*>( i->get() ); if ( !originalDrawable ) continue; // go through the list of input features... for( FeatureList::const_iterator j = _features.begin(); j != _features.end(); j++ ) { Feature* feature = j->get(); osg::Matrixd scaleMatrix; if ( _symbol->scale().isSet() ) { double scale = feature->eval( _scaleExpr, &_cx ); scaleMatrix.makeScale( scale, scale, scale ); } osg::Matrixd rotationMatrix; if ( _modelSymbol && _modelSymbol->heading().isSet() ) { float heading = feature->eval( _headingExpr, &_cx ); rotationMatrix.makeRotate( osg::Quat(osg::DegreesToRadians(heading), osg::Vec3(0,0,1)) ); } GeometryIterator gi( feature->getGeometry(), false ); while( gi.hasMore() ) { Geometry* geom = gi.next(); // if necessary, transform the points to the target SRS: if ( !_makeECEF && !_targetSRS->isEquivalentTo(_srs) ) { _srs->transform( geom->asVector(), _targetSRS ); } for( Geometry::const_iterator k = geom->begin(); k != geom->end(); ++k ) { osg::Vec3d point = *k; osg::Matrixd mat; if ( _makeECEF ) { osg::Matrixd rotation; ECEF::transformAndGetRotationMatrix( point, _srs, point, _targetSRS, rotation ); mat = rotationMatrix * rotation * scaleMatrix * osg::Matrixd::translate(point) * _f2n->world2local(); } else { mat = rotationMatrix * scaleMatrix * osg::Matrixd::translate(point) * _f2n->world2local(); } // clone the source drawable once for each input feature. osg::ref_ptr<osg::Geometry> newDrawable = osg::clone( originalDrawable, osg::CopyOp::DEEP_COPY_ARRAYS | osg::CopyOp::DEEP_COPY_PRIMITIVES ); osg::Vec3Array* verts = dynamic_cast<osg::Vec3Array*>( newDrawable->getVertexArray() ); if ( verts ) { for( osg::Vec3Array::iterator v = verts->begin(); v != verts->end(); ++v ) { (*v).set( (*v) * mat ); } // add the new cloned, translated drawable back to the geode. geode.addDrawable( newDrawable.get() ); if ( _cx.featureIndex() ) _cx.featureIndex()->tagPrimitiveSets( newDrawable.get(), feature ); } } } } } geode.dirtyBound(); MeshConsolidator::run( geode ); osg::NodeVisitor::apply( geode ); }
void MeshConsolidator::run( osg::Geode& geode ) { bool useVBOs = false; // NOTE: we'd rather use the IndexMeshVisitor instead of our own code here, // but the IMV does not preserve the user data attached to the primitive sets. // We need that since it holds the feature index information. //osgUtil::IndexMeshVisitor mesher; //geode.accept(mesher); // trivial bailout: if ( geode.getNumDrawables() <= 1 ) return; // list of geometries to consolidate and not to consolidate. DrawableList consolidate, dontConsolidate; // list of texture coordinate array image units in use std::vector<unsigned> texCoordArrayUnits; texCoordArrayUnits.reserve(32); // sort the drawables: for( unsigned i=0; i<geode.getNumDrawables(); ++i ) { osg::Geometry* geom = geode.getDrawable(i)->asGeometry(); if ( geom ) { if ( canOptimize(*geom) ) { // convert all primitives to triangles. convertToTriangles( *geom ); // NOTE!! tex/attrib array counts much already be equal. if ( texCoordArrayUnits.size() == 0 ) { for( unsigned u=0; u<32; ++u ) { if ( geom->getTexCoordArray(u) != 0L ) texCoordArrayUnits.push_back( u ); } if ( geom->getUseVertexBufferObjects() ) useVBOs = true; } consolidate.push_back(geom); } else { dontConsolidate.push_back(geom); } } } // start consolidating the geometries. unsigned targetNumVertsPerGeom = 100000; //TODO: configurable? DrawableList results; unsigned numVerts = 0, numColors = 0, numNormals = 0; DrawableList::iterator start = consolidate.begin(); for( DrawableList::iterator end = consolidate.begin(); end != consolidate.end(); ) { osg::Geometry* geom = end->get()->asGeometry(); // already type-checked this earlier. unsigned geomNumVerts = geom->getVertexArray()->getNumElements(); ++end; numVerts += geomNumVerts; if ( geom->getColorArray() ) numColors += geom->getColorArray()->getNumElements(); if ( geom->getNormalArray() ) numNormals += geom->getNormalArray()->getNumElements(); if ( numVerts > targetNumVertsPerGeom || end == consolidate.end() ) { OE_DEBUG << LC << "Merging " << ((unsigned)(end-start)) << " geoms with " << numVerts << " verts." << std::endl; merge( start, end, numVerts, numColors, numNormals, texCoordArrayUnits, useVBOs, results ); start = end; numVerts = 0, numColors = 0, numNormals = 0; } } // re-build the geode: geode.removeDrawables( 0, geode.getNumDrawables() ); for( DrawableList::iterator i = results.begin(); i != results.end(); ++i ) geode.addDrawable( i->get() ); for( DrawableList::iterator i = dontConsolidate.begin(); i != dontConsolidate.end(); ++i ) geode.addDrawable( i->get() ); }
nave(int x,int y, int z, int tamaño) { pyramidGeode = new osg::Geode(); pyramidGeometry = new osg::Geometry(); pyramidGeode->addDrawable(pyramidGeometry); osg::Vec3Array* pyramidVertices = new osg::Vec3Array; //0-4 pyramidVertices->push_back( osg::Vec3( x, y, z) ); // front left //1-5 pyramidVertices->push_back( osg::Vec3(tamaño+x, y, z) ); // front right //2-6 pyramidVertices->push_back( osg::Vec3(tamaño+x,tamaño+y, z) ); // back right //3-7 pyramidVertices->push_back( osg::Vec3( x,tamaño+y, z) ); // back left //4-0 pyramidVertices->push_back( osg::Vec3( x, y,tamaño+z) ); // peak //5-1 pyramidVertices->push_back( osg::Vec3(tamaño+x, y,tamaño+z) ); // front right //6-2 pyramidVertices->push_back( osg::Vec3(tamaño+x,tamaño+y,tamaño+z) ); // back right //7-3 pyramidVertices->push_back( osg::Vec3( x,tamaño+y,tamaño+z) ); // back left pyramidGeometry->setVertexArray( pyramidVertices ); osg::DrawElementsUInt* pyramidBase = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0); pyramidBase->push_back(3); pyramidBase->push_back(2); pyramidBase->push_back(1); pyramidBase->push_back(0); pyramidGeometry->addPrimitiveSet(pyramidBase); osg::DrawElementsUInt* pyramidTop = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0); pyramidTop->push_back(4); pyramidTop->push_back(5); pyramidTop->push_back(6); pyramidTop->push_back(7); pyramidGeometry->addPrimitiveSet(pyramidTop); //Repeat the same for each of the four sides. Again, vertices are //specified in counter-clockwise order. osg::DrawElementsUInt* pyramidFaceOne = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0); pyramidFaceOne->push_back(0); pyramidFaceOne->push_back(1); pyramidFaceOne->push_back(5); pyramidFaceOne->push_back(4); pyramidGeometry->addPrimitiveSet(pyramidFaceOne); osg::DrawElementsUInt* pyramidFaceTwo = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0); pyramidFaceTwo->push_back(1); pyramidFaceTwo->push_back(2); pyramidFaceTwo->push_back(6); pyramidFaceTwo->push_back(5); pyramidGeometry->addPrimitiveSet(pyramidFaceTwo); osg::DrawElementsUInt* pyramidFaceThree = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0); pyramidFaceThree->push_back(2); pyramidFaceThree->push_back(3); pyramidFaceThree->push_back(7); pyramidFaceThree->push_back(6); pyramidGeometry->addPrimitiveSet(pyramidFaceThree); osg::DrawElementsUInt* pyramidFaceFour = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0); pyramidFaceFour->push_back(3); pyramidFaceFour->push_back(0); pyramidFaceThree->push_back(4); pyramidFaceFour->push_back(7); pyramidGeometry->addPrimitiveSet(pyramidFaceFour); //Declare and load an array of Vec4 elements to store colors. osg::Vec4Array* colors = new osg::Vec4Array; colors->push_back(osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f) ); //index 0 red colors->push_back(osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f) ); //index 1 green colors->push_back(osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f) ); //index 2 blue colors->push_back(osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f) ); //index 3 white colors->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f) ); //index 4 red colors->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f) ); //index 4 red colors->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f) ); //index 4 red colors->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f) ); //index 4 red //The next step is to associate the array of colors with the geometry, //assign the color indices created above to the geometry and set the //binding mode to _PER_VERTEX. pyramidGeometry->setColorArray(colors); pyramidGeometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX); };
void MeshConsolidator::run( osg::Geode& geode ) { unsigned numVerts = 0; unsigned numColors = 0; unsigned numNormals = 0; unsigned numTexCoordArrays = 0; unsigned numVertAttribArrays = 0; std::vector<unsigned> texCoordArrayUnits; texCoordArrayUnits.reserve(32); osg::Geometry::AttributeBinding newColorsBinding; osg::Geometry::AttributeBinding newNormalsBinding; bool useVBOs = false; GLenum usage = GL_STATIC_DRAW_ARB; // first, triangulate all the geometries and count all the components: for( unsigned i=0; i<geode.getNumDrawables(); ++i ) { osg::Geometry* geom = geode.getDrawable(i)->asGeometry(); if ( geom ) { if ( !canOptimize(*geom) ) continue; if ( geom->getUseVertexBufferObjects() ) { useVBOs = true; osg::BufferObject* bo = geom->getVertexArray()->getVertexBufferObject(); if ( bo ) usage = bo->getUsage(); } // optimize it into triangles first: MeshConsolidator::run( *geom ); osg::Array* verts = geom->getVertexArray(); if ( verts ) numVerts += verts->getNumElements(); osg::Array* colors = geom->getColorArray(); if ( colors ) numColors += colors->getNumElements(); osg::Array* normals = geom->getNormalArray(); if ( normals ) numNormals += normals->getNumElements(); // NOTE!! tex/attrib array counts much already be equal. if ( texCoordArrayUnits.size() == 0 ) { for( unsigned u=0; u<32; ++u ) { if ( geom->getTexCoordArray(u) != 0L ) texCoordArrayUnits.push_back( u ); } } numVertAttribArrays += geom->getNumVertexAttribArrays(); } } // bail if there are unsupported items in there. if (geode.getNumDrawables() < 2 || //numTexCoordArrays > 0 || numVertAttribArrays > 0 ) { return; } osg::Vec3Array* newVerts = new osg::Vec3Array(); newVerts->reserve( numVerts ); osg::Vec4Array* newColors =0L; if ( numColors > 0 ) { newColors = new osg::Vec4Array(); newColors->reserve( numVerts ); newColorsBinding = osg::Geometry::BIND_PER_VERTEX; //newColors->reserve( numColors==numVerts? numColors : 1 ); //newColorsBinding = numColors==numVerts? osg::Geometry::BIND_PER_VERTEX : osg::Geometry::BIND_OVERALL; } osg::Vec3Array* newNormals =0L; if ( numNormals > 0 ) { newNormals = new osg::Vec3Array(); newNormals->reserve( numVerts ); newNormalsBinding = osg::Geometry::BIND_PER_VERTEX; //newNormals->reserve( numNormals==numVerts? numNormals : 1 ); //newNormalsBinding = numNormals==numVerts? osg::Geometry::BIND_PER_VERTEX : osg::Geometry::BIND_OVERALL; } std::vector<osg::Vec2Array*> newTexCoordsArrays; for( unsigned i=0; i<texCoordArrayUnits.size(); ++i ) { osg::Vec2Array* newTexCoords = new osg::Vec2Array(); newTexCoords->reserve( numVerts ); newTexCoordsArrays.push_back( newTexCoords ); } unsigned offset = 0; osg::Geometry::PrimitiveSetList newPrimSets; std::vector<osg::ref_ptr<osg::Geometry> > nonOptimizedGeoms; osg::StateSet* unifiedStateSet = 0L; for( unsigned i=0; i<geode.getNumDrawables(); ++i ) { osg::Geometry* geom = geode.getDrawable(i)->asGeometry(); if ( geom ) { if ( !canOptimize(*geom) ) { nonOptimizedGeoms.push_back(geom); continue; } // merge in the stateset: if ( unifiedStateSet == 0L ) unifiedStateSet = geom->getStateSet(); else if ( geom->getStateSet() ) unifiedStateSet->merge( *geom->getStateSet() ); // copy over the verts: osg::Vec3Array* geomVerts = dynamic_cast<osg::Vec3Array*>( geom->getVertexArray() ); if ( geomVerts ) { std::copy( geomVerts->begin(), geomVerts->end(), std::back_inserter(*newVerts) ); if ( newColors ) { osg::Vec4Array* colors = dynamic_cast<osg::Vec4Array*>( geom->getColorArray() ); if ( colors ) { if ( newColorsBinding == osg::Geometry::BIND_PER_VERTEX ) { std::copy( colors->begin(), colors->end(), std::back_inserter(*newColors) ); } else if ( i == 0 ) // overall { newColors->push_back( (*colors)[0] ); } } } if ( newNormals ) { osg::Vec3Array* normals = dynamic_cast<osg::Vec3Array*>( geom->getNormalArray() ); if ( normals ) { if ( newNormalsBinding == osg::Geometry::BIND_PER_VERTEX ) { std::copy( normals->begin(), normals->end(), std::back_inserter(*newNormals) ); } else if ( i == 0 ) // overall { newNormals->push_back( (*normals)[0] ); } } } if ( newTexCoordsArrays.size() > 0 ) { for( unsigned a=0; a<texCoordArrayUnits.size(); ++a ) { unsigned unit = texCoordArrayUnits[a]; osg::Vec2Array* texCoords = dynamic_cast<osg::Vec2Array*>( geom->getTexCoordArray(unit) ); if ( texCoords ) { osg::Vec2Array* newTexCoords = newTexCoordsArrays[a]; std::copy( texCoords->begin(), texCoords->end(), std::back_inserter(*newTexCoords) ); } } } osg::ref_ptr<osg::Referenced> sharedUserData; for( unsigned j=0; j < geom->getNumPrimitiveSets(); ++j ) { osg::PrimitiveSet* pset = geom->getPrimitiveSet(j); osg::PrimitiveSet* newpset = 0L; // all primsets have the same user data (or else we would not have made it this far // since canOptimize would be false) if ( !sharedUserData.valid() ) sharedUserData = pset->getUserData(); if ( dynamic_cast<osg::DrawElementsUByte*>(pset) ) newpset = remake( static_cast<osg::DrawElementsUByte*>(pset), numVerts, offset ); else if ( dynamic_cast<osg::DrawElementsUShort*>(pset) ) newpset = remake( static_cast<osg::DrawElementsUShort*>(pset), numVerts, offset ); else if ( dynamic_cast<osg::DrawElementsUInt*>(pset) ) newpset = remake( static_cast<osg::DrawElementsUInt*>(pset), numVerts, offset ); else if ( dynamic_cast<osg::DrawArrays*>(pset) ) newpset = convertDAtoDE( static_cast<osg::DrawArrays*>(pset), numVerts, offset ); if ( newpset ) { newpset->setUserData( sharedUserData.get() ); newPrimSets.push_back( newpset ); } } offset += geomVerts->size(); } } } // assemble the new geometry. osg::Geometry* newGeom = new osg::Geometry(); newGeom->setUseVertexBufferObjects( useVBOs ); newGeom->setVertexArray( newVerts ); if ( useVBOs && newVerts->getVertexBufferObject() ) newVerts->getVertexBufferObject()->setUsage( usage ); if ( newColors ) { newGeom->setColorArray( newColors ); newGeom->setColorBinding( newColorsBinding ); } if ( newNormals ) { newGeom->setNormalArray( newNormals ); newGeom->setNormalBinding( newNormalsBinding ); } if ( newTexCoordsArrays.size() > 0 ) { for( unsigned a=0; a<texCoordArrayUnits.size(); ++a ) { unsigned unit = texCoordArrayUnits[a]; newGeom->setTexCoordArray( unit, newTexCoordsArrays[a] ); } } newGeom->setPrimitiveSetList( newPrimSets ); newGeom->setStateSet( unifiedStateSet ); // replace the geode's drawables geode.removeDrawables( 0, geode.getNumDrawables() ); geode.addDrawable( newGeom ); for( std::vector<osg::ref_ptr<osg::Geometry> >::iterator i = nonOptimizedGeoms.begin(); i != nonOptimizedGeoms.end(); ++i ) geode.addDrawable( i->get() ); }