osgEarth 2.1.1
|
00001 /* -*-c++-*- */ 00002 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph 00003 * Copyright 2008-2010 Pelican Mapping 00004 * http://osgearth.org 00005 * 00006 * osgEarth is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU Lesser General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public License 00017 * along with this program. If not, see <http://www.gnu.org/licenses/> 00018 */ 00019 #include <osgEarthSymbology/GeometryRasterizer> 00020 #include <osgEarthSymbology/PointSymbol> 00021 #include <osgEarthSymbology/LineSymbol> 00022 #include <osgEarthSymbology/PolygonSymbol> 00023 #include <osgEarthSymbology/AGG.h> 00024 00025 using namespace osgEarth::Symbology; 00026 00027 #define LC "[GeometryRasterizer] " 00028 00029 // -------------------------------------------------------------------------- 00030 00031 struct AggState : public osg::Referenced 00032 { 00033 AggState( osg::Image* image ) 00034 : _rbuf( image->data(), image->s(), image->t(), image->s()*4 ), 00035 _ren( _rbuf ) 00036 { 00037 _ras.gamma( 1.3 ); 00038 _ras.filling_rule( agg::fill_even_odd ); 00039 00040 // pre-clear the buffer.... 00041 _ren.clear(agg::rgba8(0,0,0,0)); 00042 } 00043 00044 agg::rendering_buffer _rbuf; 00045 agg::renderer<agg::span_abgr32> _ren; 00046 agg::rasterizer _ras; 00047 }; 00048 00049 // -------------------------------------------------------------------------- 00050 00051 GeometryRasterizer::GeometryRasterizer( int width, int height, const Style& style ) : 00052 _style( style ) 00053 { 00054 _image = new osg::Image(); 00055 _image->allocateImage( width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE ); 00056 _image->setAllocationMode( osg::Image::USE_NEW_DELETE ); 00057 _state = new AggState( _image.get() ); 00058 } 00059 00060 osg::Image* 00061 GeometryRasterizer::finalize() 00062 { 00063 //convert from ABGR to RGBA 00064 unsigned char* pixel = _image->data(); 00065 for(int i=0; i<_image->s()*_image->t()*4; i+=4, pixel+=4) 00066 { 00067 std::swap( pixel[0], pixel[3] ); 00068 std::swap( pixel[1], pixel[2] ); 00069 } 00070 osg::Image* result = _image.release(); 00071 _image = 0L; 00072 return result; 00073 } 00074 00075 void 00076 GeometryRasterizer::draw( const Geometry* geom, const osg::Vec4f& c ) 00077 { 00078 if ( !_image.valid() ) return; 00079 00080 AggState* state = static_cast<AggState*>( _state.get() ); 00081 00082 osg::Vec4f color = c; 00083 osg::ref_ptr<const Geometry> geomToRender = geom; 00084 00085 if ( geom->getType() == Geometry::TYPE_POLYGON ) 00086 { 00087 const PolygonSymbol* ps = _style.getSymbol<const PolygonSymbol>(); 00088 if ( ps ) 00089 color = ps->fill()->color(); 00090 } 00091 else 00092 { 00093 const LineSymbol* ls = _style.getSymbol<const LineSymbol>(); 00094 float distance = ls ? ls->stroke()->width().value() * 0.5f : 1.0f; 00095 osg::ref_ptr<Geometry> bufferedGeom; 00096 if ( !geom->buffer( distance, bufferedGeom ) ) 00097 { 00098 OE_WARN << LC << "Failed to draw line; buffer op not available" << std::endl; 00099 return; 00100 } 00101 geomToRender = bufferedGeom.get(); 00102 if ( ls ) 00103 color = ls->stroke()->color(); 00104 } 00105 00106 float a = 127+(color.a()*255)/2; // scale alpha up 00107 agg::rgba8 fgColor = agg::rgba8( (unsigned int)(color.r()*255), (unsigned int)(color.g()*255), (unsigned int)(color.b()*255), (unsigned int)a ); 00108 00109 ConstGeometryIterator gi( geomToRender.get() ); 00110 while( gi.hasMore() ) 00111 { 00112 const Vec3dVector& g = gi.next()->asVector(); 00113 00114 for( Vec3dVector::const_iterator p = g.begin(); p != g.end(); p++ ) 00115 { 00116 const osg::Vec3d& p0 = *p; 00117 00118 if ( p == g.begin() ) 00119 state->_ras.move_to_d( p0.x(), p0.y() ); 00120 else 00121 state->_ras.line_to_d( p0.x(), p0.y() ); 00122 } 00123 } 00124 state->_ras.render( state->_ren, fgColor ); 00125 state->_ras.reset(); 00126 } 00127