osgEarth 2.1.1

/home/cube/sources/osgearth/src/osgEarthDrivers/engine_droam/AMRGeometry.cpp

Go to the documentation of this file.
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 "Common"
00020 #include "AMRGeometry"
00021 #include <osg/State>
00022 #include <osg/Uniform>
00023 #include <osgEarth/Notify>
00024 
00025 #define LC "[AMRGeometry] "
00026 
00027 // --------------------------------------------------------------------------
00028 
00029 #include "AMRShaders.h"
00030 
00031 // --------------------------------------------------------------------------
00032 
00033 AMRTriangle::AMRTriangle()
00034 {
00035     _stateSet = new osg::StateSet();
00036 
00037     // should this be INT_SAMPLER_2D?
00038     _stateSet->getOrCreateUniform( "tex0", osg::Uniform::INT )->set( 0 );
00039 }
00040 
00041 #define SET_UNIFORM(X,Y,Z) \
00042     _stateSet->getOrCreateUniform( X , Y )->set( Z )
00043 
00044 
00045 AMRTriangle::AMRTriangle(const MeshNode& n0, const osg::Vec2& t0,
00046                          const MeshNode& n1, const osg::Vec2& t1, 
00047                          const MeshNode& n2, const osg::Vec2& t2) :
00048 _node0(n0), _node1(n1), _node2(n2)
00049 {
00050     _stateSet = new osg::StateSet();
00051     // should this be INT_SAMPLER_2D?
00052     SET_UNIFORM( "tex0", osg::Uniform::INT, 0 );
00053 
00054     SET_UNIFORM( "c0", osg::Uniform::FLOAT_VEC3, _node0._geodeticCoord );
00055     SET_UNIFORM( "c1", osg::Uniform::FLOAT_VEC3, _node1._geodeticCoord );
00056     SET_UNIFORM( "c2", osg::Uniform::FLOAT_VEC3, _node2._geodeticCoord );
00057 
00058     SET_UNIFORM( "v0", osg::Uniform::FLOAT_VEC3, _node0._vertex );
00059     SET_UNIFORM( "v1", osg::Uniform::FLOAT_VEC3, _node1._vertex );
00060     SET_UNIFORM( "v2", osg::Uniform::FLOAT_VEC3, _node2._vertex );
00061 
00062     SET_UNIFORM( "t0", osg::Uniform::FLOAT_VEC2, t0 );
00063     SET_UNIFORM( "t1", osg::Uniform::FLOAT_VEC2, t1 );
00064     SET_UNIFORM( "t2", osg::Uniform::FLOAT_VEC2, t2 );
00065 
00066     SET_UNIFORM( "n0", osg::Uniform::FLOAT_VEC3, _node0._normal );
00067     SET_UNIFORM( "n1", osg::Uniform::FLOAT_VEC3, _node1._normal );
00068     SET_UNIFORM( "n2", osg::Uniform::FLOAT_VEC3, _node2._normal );
00069 
00070     SET_UNIFORM( "r0", osg::Uniform::FLOAT_VEC4, _node0._geodeticRot.asVec4() );
00071     SET_UNIFORM( "r1", osg::Uniform::FLOAT_VEC4, _node1._geodeticRot.asVec4() );
00072     SET_UNIFORM( "r2", osg::Uniform::FLOAT_VEC4, _node2._geodeticRot.asVec4() );
00073 }
00074 
00075 void
00076 AMRTriangle::expand( osg::BoundingBox& box )
00077 {
00078     box.expandBy( _node0._vertex );
00079     box.expandBy( _node1._vertex );
00080     box.expandBy( _node2._vertex );
00081 }
00082 
00083 // --------------------------------------------------------------------------
00084 
00085 AMRDrawable::AMRDrawable()
00086 {
00087     _stateSet = new osg::StateSet();
00088 }
00089 
00090 // --------------------------------------------------------------------------
00091 
00092 AMRGeometry::AMRGeometry()
00093 {
00094     initShaders();
00095     initPatterns();
00096 
00097     //this->setBound( osg::BoundingBox(-1e10, -1e10, -1e10, 1e10, 1e10, 1e10) );
00098 }
00099 
00100 AMRGeometry::AMRGeometry( const AMRGeometry& rhs, const osg::CopyOp& op ) :
00101 osg::Drawable( rhs, op ) //osg::Geometry( rhs, op )
00102 {
00103     //todo
00104     setInitialBound( osg::BoundingBox(-1e10, -1e10, -1e10, 1e10, 1e10, 1e10) );
00105 }
00106 
00107 osg::BoundingBox
00108 AMRGeometry::computeBound() const
00109 {
00110     osg::BoundingBox box;
00111     for( AMRDrawableList::const_iterator i = _drawList.begin(); i != _drawList.end(); ++i )
00112     {
00113         const AMRTriangleList& prims = i->get()->_triangles;
00114         for( AMRTriangleList::const_iterator j = prims.begin(); j != prims.end(); ++j )
00115         {
00116             j->get()->expand( box );
00117         }
00118     } 
00119     return box;
00120 }
00121 
00122 void
00123 AMRGeometry::clearDrawList()
00124 {
00125     if ( _drawList.size() > 0 )
00126     {
00127         _drawList.clear();
00128         dirtyBound();
00129     }
00130 }
00131 
00132 void
00133 AMRGeometry::setDrawList( const AMRDrawableList& drawList )
00134 {
00135     _drawList = drawList;
00136     dirtyBound();
00137 }
00138 
00139 void
00140 AMRGeometry::initShaders()
00141 {
00142     // initialize the shader program.
00143     _program = new osg::Program();
00144     _program->setName( "AMRGeometry" );
00145 
00146     osg::Shader* vertexShader = new osg::Shader( osg::Shader::VERTEX,
00147         //std::string( source_vertShaderMain_flatMethod )
00148         std::string( source_vertShaderMain_geocentricMethod ) +
00149         std::string( source_geodeticToXYZ ) +
00150         std::string( source_rotVecToGeodetic )
00151         //std::string( source_vertShaderMain_latLonMethod )
00152         //std::string( source_vertShaderMain_slerpMethod )
00153         );
00154 
00155     vertexShader->setName( "AMR Vert Shader" );
00156     _program->addShader( vertexShader );
00157 
00158     osg::Shader* fragmentShader = new osg::Shader( osg::Shader::FRAGMENT,
00159         std::string( source_fragShaderMain )
00160         );
00161 
00162     fragmentShader->setName( "AMR Frag Shader" );
00163     _program->addShader( fragmentShader );
00164 
00165     // the shader program:
00166     this->getOrCreateStateSet()->setAttribute( _program.get(), osg::StateAttribute::ON );
00167 }
00168 
00169 static void
00170 toBarycentric(const osg::Vec3& p1, const osg::Vec3& p2, const osg::Vec3& p3, 
00171               const osg::Vec3& in,
00172               osg::Vec3& outVert, osg::Vec2& outTex )
00173 {
00174     //from: http://forums.cgsociety.org/archive/index.php/t-275372.html
00175     osg::Vec3 
00176         v1 = in - p1,
00177         v2 = in - p2,
00178         v3 = in - p3;
00179 
00180     double 
00181         area1 = 0.5 * (v2 ^ v3).length(),
00182         area2 = 0.5 * (v1 ^ v3).length(),
00183         area3 = 0.5 * (v1 ^ v2).length();
00184 
00185     double fullArea = area1 + area2 + area3;
00186 
00187     double u = area1/fullArea;
00188     double v = area2/fullArea;
00189     double w = area3/fullArea; 
00190 
00191     outVert.set( u, v, w );
00192 
00193     // tex coords
00194     osg::Vec2 t1( p1.x(), p1.y() );
00195     osg::Vec2 t2( p2.x(), p2.y() );
00196     osg::Vec2 t3( p3.x(), p3.y() );
00197     outTex = t1*w + t2*v + t3*u;
00198 }
00199 
00200 
00201 void
00202 AMRGeometry::initPatterns()
00203 {
00204     _numPatternVerts = 0;
00205     _numPatternElements = 0;
00206     _numPatternStrips = 0;
00207     _numPatternTriangles = 0;
00208 
00209     this->setUseVertexBufferObjects( true );
00210     this->setUseDisplayList( false );
00211 
00212     _patternVBO = new osg::VertexBufferObject();
00213 
00214     _verts = new osg::Vec3Array();
00215     _verts->setVertexBufferObject( _patternVBO.get() );
00216 
00217     _texCoords = new osg::Vec2Array();
00218     _texCoords->setVertexBufferObject( _patternVBO.get() );
00219  
00220     // build a right-triangle pattern. (0,0) is the lower-left (90d),
00221     // (0,1) is the lower right (45d) and (1,0) is the upper-left (45d)
00222     osg::Vec3f p1(0,0,0), p2(0,1,0), p3(1,0,0);
00223 
00224     for( int r=AMR_PATCH_ROWS-1; r >=0; --r )
00225     {
00226         int cols = AMR_PATCH_ROWS-r;
00227         //OE_INFO << "ROW " << r << std::endl;
00228         for( int c=0; c<cols; ++c )
00229         {
00230             osg::Vec3 point( (float)c/(float)(AMR_PATCH_ROWS-1), (float)r/(float)(AMR_PATCH_ROWS-1), 0 );
00231             osg::Vec3 baryVert;
00232             osg::Vec2 baryTex;
00233             toBarycentric( p1, p2, p3, point, baryVert, baryTex );
00234             _verts->push_back( baryVert );
00235             _texCoords->push_back( baryTex );
00236         }
00237     }
00238     _numPatternVerts = _verts->size();
00239 
00240     unsigned short off = 0;
00241     unsigned short rowptr = off;
00242 
00243     _patternEBO = new osg::ElementBufferObject();
00244 
00245     for( int r=1; r<AMR_PATCH_ROWS; ++r )
00246     {
00247         rowptr += r;
00248         osg::DrawElementsUShort* e = new osg::DrawElementsUShort( GL_TRIANGLE_STRIP );
00249         e->setElementBufferObject( _patternEBO.get() );            
00250 
00251         for( int c=0; c<=r; ++c )
00252         {
00253             e->push_back( rowptr + c );               
00254             if ( c < r )
00255                 e->push_back( rowptr + c - r );
00256         }
00257         OE_INFO << std::endl;
00258         _pattern.push_back( e );
00259 
00260         _numPatternStrips++;
00261         _numPatternElements += e->size();
00262         _numPatternTriangles += (e->size()-1)/2;     
00263     }
00264 
00265     OE_INFO << LC
00266         << "Pattern: "   << std::dec
00267         << "verts="      << _numPatternVerts
00268         << ", strips="   << _numPatternStrips
00269         << ", tris="     << _numPatternTriangles
00270         << ", elements=" << _numPatternElements
00271         << std::endl;
00272 }
00273 
00274 static int s_numTemplates = 0;
00275 
00276 void
00277 AMRGeometry::drawImplementation( osg::RenderInfo& renderInfo ) const
00278 {   
00279     osg::State& state = *renderInfo.getState();
00280     
00281     // bind the VBO:
00282     state.setVertexPointer( _verts.get() );
00283 
00284     // bind the texture coordinate arrrays:
00285     state.setTexCoordPointer( 0, _texCoords.get() );
00286 
00287     // this will enable the amr geometry's stateset (and activate the Program)
00288     state.pushStateSet( this->getStateSet() );
00289     //state.pushStateSet(0L);
00290     //_program->apply( state );
00291 
00292     int numTemplates = 0;
00293 
00294     for( AMRDrawableList::const_iterator i = _drawList.begin(); i != _drawList.end(); ++i )
00295     {
00296         const AMRDrawable* drawable = i->get();
00297 
00298         // apply the drawable's state changes:
00299         state.pushStateSet( drawable->_stateSet.get() );
00300 
00301         for( AMRTriangleList::const_iterator j = drawable->_triangles.begin(); j != drawable->_triangles.end(); ++j )
00302         {
00303             const AMRTriangle* dtemplate = j->get();
00304 
00305             // apply the primitive's state changes:
00306             state.apply( dtemplate->_stateSet.get() );
00307 
00308             // render the pattern (a collection of primitive sets)
00309             for( Pattern::const_iterator p = _pattern.begin(); p != _pattern.end(); ++p )
00310             {
00311                 p->get()->draw( state, true );
00312             }
00313 
00314             numTemplates++;
00315         }
00316 
00317         state.popStateSet();
00318     }
00319 
00320     if ( s_numTemplates != numTemplates )
00321     {
00322         s_numTemplates = numTemplates;
00323         OE_INFO << LC << std::dec 
00324             << "templates="  << numTemplates
00325             << ", verts="    << numTemplates*_numPatternVerts
00326             << ", strips="   << numTemplates*_numPatternStrips
00327             << ", tris="     << numTemplates*_numPatternTriangles
00328             << ", elements=" << numTemplates*_numPatternElements
00329             << std::endl;
00330     }
00331 
00332     // unbind the buffer objects.
00333     state.unbindVertexBufferObject();
00334     state.unbindElementBufferObject();
00335 
00336     // undo the program.
00337     state.popStateSet();
00338 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines