|
osgEarth 2.1.1
|
Public Member Functions | |
| GeometryExtrudeSymbolizer () | |
| osg::Geode * | extrude (Geometry *geom, double offset, double height, SymbolizerContext *context) |
| void | tessellate (osg::Geometry *geom) |
| bool | compile (State< GeometryContent > *state, osg::Group *attachPoint) |
Definition at line 29 of file GeometryExtrudeSymbolizer.
| GeometryExtrudeSymbolizer::GeometryExtrudeSymbolizer | ( | ) |
Definition at line 31 of file GeometryExtrudeSymbolizer.cpp.
{
}
| bool GeometryExtrudeSymbolizer::compile | ( | State< GeometryContent > * | state, |
| osg::Group * | attachPoint | ||
| ) |
Definition at line 46 of file GeometryExtrudeSymbolizer.cpp.
{
if ( !state || !attachPoint || !state->getContent() || !state->getStyle() )
return false;
osg::ref_ptr<osg::Group> newSymbolized = new osg::Group;
const GeometryList& geometryList = state->getContent()->getGeometryList();
for (GeometryList::const_iterator it = geometryList.begin(); it != geometryList.end(); ++it)
{
Geometry* geometry = *it;
if (!geometry)
continue;
GeometryIterator geomIterator( geometry );
geomIterator.traverseMultiGeometry() = true;
geomIterator.traversePolygonHoles() = true;
while( geomIterator.hasMore() )
{
Geometry* part = geomIterator.next();
if (!part)
continue;
osg::Vec4 color = osg::Vec4(1.0, 0.0, 1.0, 1.);
float height = 1.0;
float offset = 1.0;
switch( part->getType())
{
case Geometry::TYPE_LINESTRING:
case Geometry::TYPE_RING:
{
const ExtrudedLineSymbol* line = state->getStyle()->getSymbol<ExtrudedLineSymbol>();
if (line)
{
color = line->stroke()->color();
height = line->extrude()->height();
offset = line->extrude()->offset();
}
}
break;
case Geometry::TYPE_POLYGON:
{
const ExtrudedPolygonSymbol* polygon = state->getStyle()->getSymbol<ExtrudedPolygonSymbol>();
if (polygon)
{
color = polygon->fill()->color();
height = polygon->extrude()->height();
offset = polygon->extrude()->offset();
}
}
break;
default:
continue;
break;
}
osg::Geode* geode = extrude(part, offset, height, state->getContext() );
if (geode && geode->getNumDrawables())
{
osg::Material* material = new osg::Material;
material->setDiffuse(osg::Material::FRONT_AND_BACK, color);
geode->getOrCreateStateSet()->setAttributeAndModes(material);
newSymbolized->addChild(geode);
}
}
}
if (newSymbolized->getNumChildren())
{
attachPoint->removeChildren(0, attachPoint->getNumChildren());
attachPoint->addChild(newSymbolized.get());
return true;
}
return false;
}
Here is the call graph for this function:| osg::Geode * GeometryExtrudeSymbolizer::extrude | ( | Geometry * | geom, |
| double | offset, | ||
| double | height, | ||
| SymbolizerContext * | context | ||
| ) |
Definition at line 126 of file GeometryExtrudeSymbolizer.cpp.
{
if ( !geom ) return 0L;
int numRings = 0;
// start by offsetting the input data.
{
GeometryIterator i( geom );
i.traverseMultiGeometry() = true;
i.traversePolygonHoles() = true;
while( i.hasMore() )
{
Geometry* part = i.next();
if (offset != 0.0)
{
for( osg::Vec3dArray::iterator j = part->begin(); j != part->end(); j++ )
{
{
(*j).z() += offset;
}
}
}
// in the meantime, count the # of closed geoms. We will need to know this in
// order to pre-allocate the proper # of verts.
if ( part->getType() == Geometry::TYPE_POLYGON || part->getType() == Geometry::TYPE_RING )
{
numRings++;
}
}
}
// now, go thru and remove any coplanar segments from the geometry. The tesselator will
// not work include a vert connecting two colinear segments in the tesselation, and this
// will break the stenciling logic.
#define PARALLEL_EPSILON 0.01
GeometryIterator i( geom );
i.traverseMultiGeometry() = true;
i.traversePolygonHoles() = true;
while( i.hasMore() )
{
Geometry* part = i.next();
if ( part->size() >= 3 )
{
osg::Vec3d prevVec = part->front() - part->back();
prevVec.normalize();
for( osg::Vec3dArray::iterator j = part->begin(); part->size() >= 3 && j != part->end(); )
{
osg::Vec3d& p0 = *j;
osg::Vec3d& p1 = j+1 != part->end() ? *(j+1) : part->front();
osg::Vec3d vec = p1-p0; vec.normalize();
// if the vectors are essentially parallel, remove the extraneous vertex.
if ( (prevVec ^ vec).length() < PARALLEL_EPSILON )
{
j = part->erase( j );
//OE_NOTICE << "removed colinear segment" << std::endl;
}
else
{
++j;
prevVec = vec;
}
}
}
}
bool made_geom = true;
// total up all the points so we can pre-allocate the vertex arrays.
int num_cap_verts = geom->getTotalPointCount();
int num_wall_verts = 2 * (num_cap_verts + numRings); // add in numRings b/c we need to close each wall
osg::Geometry* walls = new osg::Geometry();
osg::Vec3Array* verts = new osg::Vec3Array( num_wall_verts );
walls->setVertexArray( verts );
osg::Geometry* top_cap = new osg::Geometry();
osg::Vec3Array* top_verts = new osg::Vec3Array( num_cap_verts );
top_cap->setVertexArray( top_verts );
osg::Geometry* bottom_cap = new osg::Geometry();
osg::Vec3Array* bottom_verts = new osg::Vec3Array( num_cap_verts );
bottom_cap->setVertexArray( bottom_verts );
int wall_vert_ptr = 0;
int top_vert_ptr = 0;
int bottom_vert_ptr = 0;
//double target_len = height;
// now generate the extruded geometry.
GeometryIterator k( geom );
while( k.hasMore() )
{
Geometry* part = k.next();
unsigned int wall_part_ptr = wall_vert_ptr;
unsigned int top_part_ptr = top_vert_ptr;
unsigned int bottom_part_ptr = bottom_vert_ptr;
double part_len = 0.0;
GLenum prim_type = part->getType() == Geometry::TYPE_POINTSET ? GL_LINES : GL_TRIANGLE_STRIP;
for( osg::Vec3dArray::const_iterator m = part->begin(); m != part->end(); ++m )
{
osg::Vec3d extrude_vec;
{
extrude_vec.set( m->x(), m->y(), height );
}
(*top_verts)[top_vert_ptr++] = extrude_vec;
(*bottom_verts)[bottom_vert_ptr++] = *m;
part_len += wall_vert_ptr > wall_part_ptr?
(extrude_vec - (*verts)[wall_vert_ptr-2]).length() :
0.0;
int p;
p = wall_vert_ptr++;
(*verts)[p] = extrude_vec;
p = wall_vert_ptr++;
(*verts)[p] = *m;
}
// close the wall if it's a ring/poly:
if ( part->getType() == Geometry::TYPE_RING || part->getType() == Geometry::TYPE_POLYGON )
{
part_len += wall_vert_ptr > wall_part_ptr?
((*verts)[wall_part_ptr] - (*verts)[wall_vert_ptr-2]).length() :
0.0;
int p;
p = wall_vert_ptr++;
(*verts)[p] = (*verts)[wall_part_ptr];
p = wall_vert_ptr++;
(*verts)[p] = (*verts)[wall_part_ptr+1];
}
walls->addPrimitiveSet( new osg::DrawArrays(
prim_type,
wall_part_ptr, wall_vert_ptr - wall_part_ptr ) );
top_cap->addPrimitiveSet( new osg::DrawArrays(
osg::PrimitiveSet::LINE_LOOP,
top_part_ptr, top_vert_ptr - top_part_ptr ) );
// reverse the bottom verts so the front face is down:
std::reverse( bottom_verts->begin()+bottom_part_ptr, bottom_verts->begin()+bottom_vert_ptr );
bottom_cap->addPrimitiveSet( new osg::DrawArrays(
osg::PrimitiveSet::LINE_LOOP,
bottom_part_ptr, bottom_vert_ptr - bottom_part_ptr ) );
}
// build solid surfaces for the caps:
tessellate( top_cap );
tessellate( bottom_cap );
osg::Geode* geode = new osg::Geode();
geode->addDrawable( walls );
geode->addDrawable( top_cap );
geode->addDrawable( bottom_cap );
return geode;
}
Here is the call graph for this function:
Here is the caller graph for this function:| void GeometryExtrudeSymbolizer::tessellate | ( | osg::Geometry * | geom | ) |
Definition at line 36 of file GeometryExtrudeSymbolizer.cpp.
{
osgUtil::Tessellator tess;
tess.setTessellationType( osgUtil::Tessellator::TESS_TYPE_GEOMETRY );
tess.setWindingType( osgUtil::Tessellator::TESS_WINDING_ODD );
// tess.setWindingType( osgUtil::Tessellator::TESS_WINDING_POSITIVE );
tess.retessellatePolygons( *geom );
}
Here is the caller graph for this function:
1.7.3