FragmentList fragments(const AtomContainer& fragment, bool selected_only) { // iterate over all fragments FragmentList result; AtomContainerConstIterator it = fragment.beginAtomContainer(); for (; +it; ++it) { const Fragment* fragment = dynamic_cast<const Fragment*>(&*it); if ((fragment != 0) && (it->isSelected() || !selected_only)) { // store the fragment pointer in the list result.push_back(const_cast<Fragment*>(fragment)); } } return result; }
FragmentList BuildGeomFilter::process( Feature* input, FilterEnv* env ) { FragmentList output; // LIMITATION: this filter assumes all feature's shapes are the same // shape type! TODO: sort into bins of shape type and create a separate // geometry for each. Then merge the geometries. bool needs_tessellation = false; Fragment* frag = new Fragment(); const GeoShapeList& shapes = input->getShapes(); // if we're in batch mode, the color was resolved in the other process() function. // otherwise we still need to resolve it. osg::Vec4 color = getColorForFeature( input, env ); for( GeoShapeList::const_iterator s = shapes.begin(); s != shapes.end(); s++ ) { const GeoShape& shape = *s; if ( shape.getShapeType() == GeoShape::TYPE_POLYGON ) { needs_tessellation = true; } osg::Geometry* geom = new osg::Geometry(); // TODO: pre-total points and pre-allocate these arrays: osg::Vec3Array* verts = new osg::Vec3Array(); geom->setVertexArray( verts ); unsigned int vert_ptr = 0; // per-vertex coloring takes more memory than per-primitive-set coloring, // but it renders faster. osg::Vec4Array* colors = new osg::Vec4Array(); geom->setColorArray( colors ); geom->setColorBinding( osg::Geometry::BIND_PER_VERTEX ); //osg::Vec3Array* normals = new osg::Vec3Array(); //geom->setNormalArray( normals ); //geom->setNormalBinding( osg::Geometry::BIND_OVERALL ); //normals->push_back( osg::Vec3( 0, 0, 1 ) ); GLenum prim_type = shape.getShapeType() == GeoShape::TYPE_POINT? osg::PrimitiveSet::POINTS : shape.getShapeType() == GeoShape::TYPE_LINE? osg::PrimitiveSet::LINE_STRIP : osg::PrimitiveSet::LINE_LOOP; for( unsigned int pi = 0; pi < shape.getPartCount(); pi++ ) { unsigned int part_ptr = vert_ptr; const GeoPointList& points = shape.getPart( pi ); for( unsigned int vi = 0; vi < points.size(); vi++ ) { verts->push_back( points[vi] ); vert_ptr++; colors->push_back( color ); } geom->addPrimitiveSet( new osg::DrawArrays( prim_type, part_ptr, vert_ptr-part_ptr ) ); } // tessellate all polygon geometries. Tessellating each geometry separately // with TESS_TYPE_GEOMETRY is much faster than doing the whole bunch together // using TESS_TYPE_DRAWABLE. if ( needs_tessellation ) { osgUtil::Tessellator tess; tess.setTessellationType( osgUtil::Tessellator::TESS_TYPE_GEOMETRY ); tess.setWindingType( osgUtil::Tessellator::TESS_WINDING_POSITIVE ); tess.retessellatePolygons( *geom ); applyOverlayTexturing( geom, input, env ); } generateNormals( geom ); frag->addDrawable( geom ); } frag->addAttributes( input->getAttributes() ); applyFragmentName( frag, input, env ); output.push_back( frag ); return output; }