osgEarth 2.1.1

/home/cube/sources/osgearth/src/osgEarthDrivers/engine_droam/CubeManifold.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 "CubeManifold"
00020 #include <osgEarth/Cube>
00021 
00022 #define NEG_Y 0
00023 #define POS_Y 1
00024 #define NEG_X 2
00025 #define POS_X 3
00026 #define NEG_Z 4
00027 #define POS_Z 5
00028 
00029 #define LC "[CubeManifold] "
00030 
00031 CubeManifold::CubeManifold()
00032 {
00033     _profile = new osgEarth::UnifiedCubeProfile();
00034     _ellipsoid = _profile->getSRS()->getGeographicSRS()->getEllipsoid();
00035 }
00036 
00037 void
00038 CubeManifold::initialize( MeshManager* mesh )
00039 {
00040     // diamonds at or below level 3 are static and cannot be removed.
00041     // Level 1 is the first Quadtree Ancestor. Level 3 contains the first Quadtree
00042     // decendants (the decendants of the Level 1 quadtrees).
00043     mesh->_minGeomLevel = 1;
00044     mesh->_minActiveLevel = 3;
00045 
00046     // Construct the eight root "vertex diamonds". These are used only for their
00047     // vertex positions (as grandparents of the root edge diamonds). They have
00048     // no children or ancestors of their own.
00049     _vd[0] = new Diamond(mesh, TileKey(), 0, "vd0"); // X, -Y, Z
00050     _vd[0]->setCoord( p(1, -1, 1) );
00051     _vd[0]->_childValence = 3;
00052 
00053     _vd[1] = new Diamond(mesh, TileKey(), 0, "vd1"); // -X, Y, Z
00054     _vd[1]->setCoord( p(-1, 1, 1) );
00055     _vd[0]->_childValence = 3;
00056 
00057     _vd[2] = new Diamond(mesh, TileKey(), 0, "vd2"); // -X, -Y, -Z
00058     _vd[2]->setCoord( p(-1, -1, -1) );
00059     _vd[0]->_childValence = 3;
00060 
00061     _vd[3] = new Diamond(mesh, TileKey(), 0, "vd3"); // X, Y, -Z
00062     _vd[3]->setCoord( p(1, 1, -1) );
00063     _vd[0]->_childValence = 3;
00064 
00065     _vd[4] = new Diamond(mesh, TileKey(), 0, "vd4"); // X, Y, Z
00066     _vd[4]->setCoord( p(1, 1, 1) );
00067     _vd[0]->_childValence = 3;
00068 
00069     _vd[5] = new Diamond(mesh, TileKey(), 0, "vd5"); // -X, -Y, Z
00070     _vd[5]->setCoord( p(-1, -1, 1) );
00071     _vd[0]->_childValence = 3;
00072 
00073     _vd[6] = new Diamond(mesh, TileKey(), 0, "vd6"); // X, -Y, -Z
00074     _vd[6]->setCoord( p(1, -1, -1) );
00075     _vd[0]->_childValence = 3;
00076 
00077     _vd[7] = new Diamond(mesh, TileKey(), 0, "vd7"); // -X, Y, -Z
00078     _vd[7]->setCoord( p(-1, 1, -1) );
00079     _vd[0]->_childValence = 3;
00080 
00081     // Construct the 6 face diamonds. Exactly 2 faces parent each edge diamond (constructed
00082     // later). The vertex position of each face diamond resides as the center of that face
00083     // on the cube. The faces are carefully oriented so that child diamonds are anchored
00084     // (i.e. have their QUADTREE ancestor) at the PARENT_L and PARENT_R positions. This is
00085     // critical for proper subdivision and orientation propagation.
00086 
00087     // The first 3 share vd0 as a common PARENT_L ancestor:
00088 
00089     _fd[NEG_Y] = new Diamond(mesh, TileKey(0,1,0,_profile.get()), 1, "fd -y"); // -Y face (-90=>0 long)
00090     _fd[NEG_Y]->setCoord( p(0, -1, 0) );
00091     _fd[NEG_Y]->_a[PARENT_R] = _vd[2];
00092     _fd[NEG_Y]->_a[PARENT_L] = _vd[0];
00093     _fd[NEG_Y]->_a[QUADTREE] = _vd[5];
00094     _fd[NEG_Y]->_a[GDPARENT] = _vd[6];
00095     _fd[NEG_Y]->_orientation = 6;
00096 
00097     _fd[POS_X] = new Diamond(mesh, TileKey(0,2,0,_profile.get()), 1, "fd +x"); // +X face (0=>90 long)
00098     _fd[POS_X]->setCoord( p(1, 0, 0) );
00099     _fd[POS_X]->_a[PARENT_R] = _vd[3];
00100     _fd[POS_X]->_a[PARENT_L] = _vd[0];
00101     _fd[POS_X]->_a[QUADTREE] = _vd[6];
00102     _fd[POS_X]->_a[GDPARENT] = _vd[4];
00103     _fd[POS_X]->_orientation = 0;
00104 
00105     _fd[POS_Z] = new Diamond(mesh, TileKey(0,4,0,_profile.get()), 1, "fd +z"); // +Z face (north polar)
00106     _fd[POS_Z]->setCoord( p(0, 0, 1) );
00107     _fd[POS_Z]->_a[PARENT_R] = _vd[1];
00108     _fd[POS_Z]->_a[PARENT_L] = _vd[0];
00109     _fd[POS_Z]->_a[QUADTREE] = _vd[4];
00110     _fd[POS_Z]->_a[GDPARENT] = _vd[5];
00111     _fd[POS_Z]->_orientation = 6; // 4
00112 
00113     // The next 3 share vd7 as a common QUADTREE ancestor:
00114 
00115     _fd[POS_Y] = new Diamond(mesh, TileKey(0,3,0,_profile.get()), 1, "fd +y"); // +Y face (90=>180 long)
00116     _fd[POS_Y]->setCoord( p(0, 1, 0) );
00117     _fd[POS_Y]->_a[PARENT_R] = _vd[1];
00118     _fd[POS_Y]->_a[PARENT_L] = _vd[3];
00119     _fd[POS_Y]->_a[QUADTREE] = _vd[7];
00120     _fd[POS_Y]->_a[GDPARENT] = _vd[4];
00121     _fd[POS_Y]->_orientation = 2;
00122 
00123     _fd[NEG_X] = new Diamond(mesh, TileKey(0,0,0,_profile.get()), 1, "fd -x"); // -X face (-180=>-90 long)
00124     _fd[NEG_X]->setCoord( p(-1, 0, 0) );
00125     _fd[NEG_X]->_a[PARENT_R] = _vd[2];
00126     _fd[NEG_X]->_a[PARENT_L] = _vd[1];
00127     _fd[NEG_X]->_a[QUADTREE] = _vd[7];
00128     _fd[NEG_X]->_a[GDPARENT] = _vd[5];
00129     _fd[NEG_X]->_orientation = 0;
00130 
00131     _fd[NEG_Z] = new Diamond(mesh, TileKey(0,5,0,_profile.get()), 1, "fd -z"); // -Z face (south polar)
00132     _fd[NEG_Z]->setCoord( p(0, 0, -1) );
00133     _fd[NEG_Z]->_a[PARENT_R] = _vd[3];
00134     _fd[NEG_Z]->_a[PARENT_L] = _vd[2];
00135     _fd[NEG_Z]->_a[QUADTREE] = _vd[7];
00136     _fd[NEG_Z]->_a[GDPARENT] = _vd[6];
00137     _fd[NEG_Z]->_orientation = 0;
00138 
00139     // Next, construct the 12 root edge diamonds. These are the roots of the global
00140     // bintree, and are the first elements that actually get drawn. Each edge diamond
00141     // represents an edge of the cube, with its vertex position at the midpoint of that
00142     // edge. Each edge diamond has two face diamonds as parents, and one vertex diamond
00143     // as its "quadtree" ancestor. That adds up to the 4 verts of the diamond.
00144 
00145     // GROUP OF THREE under the vd[0] "quadtree":
00146     _ed[0] = new Diamond(mesh, TileKey(), 2, "ed0");
00147     _ed[0]->setCoord( p(0, -1, 1) );
00148     _ed[0]->_a[PARENT_R] = _fd[POS_Z];
00149     _ed[0]->_a[PARENT_L] = _fd[NEG_Y];
00150     _ed[0]->_a[QUADTREE] = _vd[0];
00151     _ed[0]->_a[GDPARENT] = _vd[5];
00152 //    _ed[0]->_color = RED;
00153 
00154     _ed[1] = new Diamond(mesh, TileKey(), 2, "ed1");
00155     _ed[1]->setCoord( p(1, -1, 0 ) );
00156     _ed[1]->_a[PARENT_R] = _fd[NEG_Y];
00157     _ed[1]->_a[PARENT_L] = _fd[POS_X];
00158     _ed[1]->_a[QUADTREE] = _vd[0];
00159     _ed[1]->_a[GDPARENT] = _vd[6];
00160     //_ed[1]->_color = RED;
00161 
00162     _ed[2] = new Diamond(mesh, TileKey(), 2, "ed2");
00163     _ed[2]->setCoord( p(1, 0, 1) );
00164     _ed[2]->_a[PARENT_R] = _fd[POS_X];
00165     _ed[2]->_a[PARENT_L] = _fd[POS_Z];
00166     _ed[2]->_a[QUADTREE] = _vd[0];
00167     _ed[2]->_a[GDPARENT] = _vd[4];
00168     //_ed[2]->_color = RED;
00169 
00170     // GROUP OF THREE under the vd[1] "quadtree":
00171     _ed[3] = new Diamond(mesh, TileKey(), 2, "ed3");
00172     _ed[3]->setCoord( p(0, 1, 1) );
00173     _ed[3]->_a[PARENT_R] = _fd[POS_Z];
00174     _ed[3]->_a[PARENT_L] = _fd[POS_Y];
00175     _ed[3]->_a[QUADTREE] = _vd[1];
00176     _ed[3]->_a[GDPARENT] = _vd[4];
00177     //_ed[3]->_color = GREEN;
00178 
00179     _ed[4] = new Diamond(mesh, TileKey(), 2, "ed4");
00180     _ed[4]->setCoord( p(-1, 1, 0) );
00181     _ed[4]->_a[PARENT_R] = _fd[POS_Y];
00182     _ed[4]->_a[PARENT_L] = _fd[NEG_X];
00183     _ed[4]->_a[QUADTREE] = _vd[1];
00184     _ed[4]->_a[GDPARENT] = _vd[7];
00185     //_ed[4]->_color = GREEN;
00186 
00187     _ed[5] = new Diamond(mesh, TileKey(), 2, "ed5");
00188     _ed[5]->setCoord( p(-1, 0, 1) );
00189     _ed[5]->_a[PARENT_R] = _fd[NEG_X];
00190     _ed[5]->_a[PARENT_L] = _fd[POS_Z];
00191     _ed[5]->_a[QUADTREE] = _vd[1];
00192     _ed[5]->_a[GDPARENT] = _vd[5];
00193     //_ed[5]->_color = GREEN;
00194 
00195     // GROUP OF THREE under the vd[2] "quadtree":
00196     _ed[6] = new Diamond(mesh, TileKey(), 2, "ed6");
00197     _ed[6]->setCoord( p(-1, -1, 0) );
00198     _ed[6]->_a[PARENT_R] = _fd[NEG_Y];
00199     _ed[6]->_a[PARENT_L] = _fd[NEG_X];
00200     _ed[6]->_a[QUADTREE] = _vd[2];
00201     _ed[6]->_a[GDPARENT] = _vd[5];
00202     //_ed[6]->_color = BLUE;
00203 
00204     _ed[7] = new Diamond(mesh, TileKey(), 2, "ed7");
00205     _ed[7]->setCoord( p(-1, 0, -1) );
00206     _ed[7]->_a[PARENT_R] = _fd[NEG_X];
00207     _ed[7]->_a[PARENT_L] = _fd[NEG_Z];
00208     _ed[7]->_a[QUADTREE] = _vd[2];
00209     _ed[7]->_a[GDPARENT] = _vd[7];
00210     //_ed[7]->_color = BLUE;
00211 
00212     _ed[8] = new Diamond(mesh, TileKey(), 2, "ed8");
00213     _ed[8]->setCoord( p(0, -1, -1) );
00214     _ed[8]->_a[PARENT_R] = _fd[NEG_Z];
00215     _ed[8]->_a[PARENT_L] = _fd[NEG_Y];
00216     _ed[8]->_a[QUADTREE] = _vd[2];
00217     _ed[8]->_a[GDPARENT] = _vd[6];
00218     //_ed[8]->_color = BLUE;
00219 
00220     // GROUP OF THREE under the vd[3] "quadtree":
00221     _ed[9] = new Diamond(mesh, TileKey(), 2, "ed9");
00222     _ed[9]->setCoord( p(1, 1, 0) );
00223     _ed[9]->_a[PARENT_R] = _fd[POS_Y];
00224     _ed[9]->_a[PARENT_L] = _fd[POS_X];
00225     _ed[9]->_a[QUADTREE] = _vd[3];
00226     _ed[9]->_a[GDPARENT] = _vd[4];
00227     //_ed[9]->_color = YELLOW;
00228 
00229     _ed[10] = new Diamond(mesh, TileKey(), 2, "ed10");
00230     _ed[10]->setCoord( p(1, 0, -1) );
00231     _ed[10]->_a[PARENT_R] = _fd[POS_X];
00232     _ed[10]->_a[PARENT_L] = _fd[NEG_Z];
00233     _ed[10]->_a[QUADTREE] = _vd[3];
00234     _ed[10]->_a[GDPARENT] = _vd[6];
00235     //_ed[10]->_color = YELLOW;
00236 
00237     _ed[11] = new Diamond(mesh, TileKey(), 2, "ed11");
00238     _ed[11]->setCoord( p(0, 1, -1) );
00239     _ed[11]->_a[PARENT_R] = _fd[NEG_Z];
00240     _ed[11]->_a[PARENT_L] = _fd[POS_Y];
00241     _ed[11]->_a[QUADTREE] = _vd[3];
00242     _ed[11]->_a[GDPARENT] = _vd[7];
00243     //_ed[11]->_color = YELLOW;
00244 
00245     // NEXT, set the pointers from each face diamond to its 4 children. We can double-
00246     // check these by looking at the ancestor assignments above. They should match up.
00247     // At the same time, we assign the back pointers from each of the edge diamonds to
00248     // their 2 parents.
00249 
00250     _fd[POS_X]->setChild( 0, _ed[10].get() );
00251     _fd[POS_X]->setChild( 1, _ed[9].get() );
00252     _fd[POS_X]->setChild( 2, _ed[2].get() );
00253     _fd[POS_X]->setChild( 3, _ed[1].get() );
00254 
00255     _fd[NEG_Y]->setChild( 0, _ed[6].get() );
00256     _fd[NEG_Y]->setChild( 1, _ed[8].get() );
00257     _fd[NEG_Y]->setChild( 2, _ed[1].get() );
00258     _fd[NEG_Y]->setChild( 3, _ed[0].get() );
00259 
00260     _fd[POS_Z]->setChild( 0, _ed[3].get() );
00261     _fd[POS_Z]->setChild( 1, _ed[5].get() );
00262     _fd[POS_Z]->setChild( 2, _ed[0].get() );
00263     _fd[POS_Z]->setChild( 3, _ed[2].get() );
00264 
00265     _fd[POS_Y]->setChild( 0, _ed[4].get() );
00266     _fd[POS_Y]->setChild( 1, _ed[3].get() );
00267     _fd[POS_Y]->setChild( 2, _ed[9].get() );
00268     _fd[POS_Y]->setChild( 3, _ed[11].get() );
00269 
00270     _fd[NEG_X]->setChild( 0, _ed[7].get() );
00271     _fd[NEG_X]->setChild( 1, _ed[6].get() );
00272     _fd[NEG_X]->setChild( 2, _ed[5].get() );
00273     _fd[NEG_X]->setChild( 3, _ed[4].get() );
00274 
00275     _fd[NEG_Z]->setChild( 0, _ed[11].get() );
00276     _fd[NEG_Z]->setChild( 1, _ed[10].get() );
00277     _fd[NEG_Z]->setChild( 2, _ed[8].get() );
00278     _fd[NEG_Z]->setChild( 3, _ed[7].get() );
00279 
00280     // seed the bouding spheres of the manifold diamonds:
00281     for( unsigned short f=0; f<6; ++f )
00282         _fd[f]->activate();
00283 
00284     for( unsigned short e=0; e<12; ++e )
00285         _ed[e]->activate();
00286 
00287     // generate Level 3 (the first renderable quadtree decendants).
00288     seed( 3 );
00289 
00290     // hopefully, that's it!
00291 }
00292 
00293 
00294 osg::Vec3d
00295 CubeManifold::p( double x, double y, double z ) const
00296 {
00297     osg::Vec3d v( x, y, z );
00298     return v;
00299 }
00300 
00301 static bool
00302 toLonLatRad( const osg::Vec3d& coord, osg::Vec3d& out_lonLat )
00303 {
00304     double lat, lon;
00305 
00306     // normalize all coordinates into the [0..1] range:
00307     double x = (1.0+coord.x())*0.5;
00308     double y = (1.0+coord.y())*0.5;
00309     double z = (1.0+coord.z())*0.5;
00310 
00311     // now convert into lat/long; this is different for each face:
00312 
00313     if ( coord.x() == 1.0 ) // positive X ( 0 <= lon <= 90, -45 <= lat <= 45 )
00314     {
00315         if ( !osgEarth::CubeUtils::faceCoordsToLatLon( y, z, 2, lat, lon ) )
00316             OE_WARN << LC << "+X: fc2ll failed" << std::endl;
00317     }
00318     else if ( coord.x() == -1.0 ) // negative X ( -180 <= lon <= -90, -45 <= lat <= 45 )
00319     {
00320         if ( !osgEarth::CubeUtils::faceCoordsToLatLon( 1.0-y, z, 0, lat, lon ) )
00321             OE_WARN << LC << "-X: fc2ll failed" << std::endl;
00322     }
00323     else if ( coord.y() == 1.0 ) // positive Y ( 90 <= lon <= 180, -45 <= lat <= 45 )
00324     {
00325         if ( !osgEarth::CubeUtils::faceCoordsToLatLon( 1.0-x, z, 3, lat, lon ) )
00326             OE_WARN << LC << "+Y: fc2ll failed" << std::endl;
00327     }
00328     else if ( coord.y() == -1.0 ) // negative Y ( -90 <= lon <= 0, -45 <= lat <= 45 )
00329     {
00330         if ( !osgEarth::CubeUtils::faceCoordsToLatLon( x, z, 1, lat, lon ) )
00331             OE_WARN << LC << "-Y: fc2ll failed" << std::endl;
00332     }
00333     else if ( coord.z() == 1.0 ) // positive Z ( -180 <= lon < 180, 45 <= lat <= 90 )
00334     {
00335         if ( !osgEarth::CubeUtils::faceCoordsToLatLon( 1.0-y, x, 4, lat, lon ) )
00336             OE_WARN << LC << "+Z: fc2ll failed" << std::endl;
00337     }
00338     else //if ( coord.z() == -1.0 ) // negative Z ( -180 <= lon < 180, -90 <= lat <= -45 )
00339     {
00340         if ( !osgEarth::CubeUtils::faceCoordsToLatLon( x, 1.0-y, 5, lat, lon ) )
00341             OE_WARN << LC << "-Z: fc2ll failed" << std::endl;
00342     }
00343 
00344     out_lonLat.x() = osg::DegreesToRadians( lon );
00345     out_lonLat.y() = osg::DegreesToRadians( lat );
00346     out_lonLat.z() = 0.0;
00347 
00348     return true;
00349 }
00350 
00351 
00352 osg::Vec3d
00353 CubeManifold::midpoint( const osg::Vec3d& p0, const osg::Vec3d& p1 ) const
00354 {
00355     return (p0+p1)*0.5;
00356 }
00357 
00358 MeshNode
00359 CubeManifold::createNode( const osg::Vec3d& manCoord ) const
00360 {
00361     MeshNode node;
00362 
00363     node._manifoldCoord = manCoord;
00364     
00365     toLonLatRad( manCoord, node._geodeticCoord ); // our manifold coords are already geodetic
00366 
00367     osg::Matrixd local2world;
00368     _ellipsoid->computeLocalToWorldTransformFromLatLongHeight(
00369         node._geodeticCoord.y(), node._geodeticCoord.x(), node._geodeticCoord.z(),
00370         local2world );
00371 
00372     node._vertex = local2world.getTrans();
00373 
00374     node._normal = node._vertex;
00375     node._normal.normalize();
00376     //node._normal = _ellipsoid->computeLocalUpVector(
00377     //    node._vertex.x(), node._vertex.y(), node._vertex.z() );
00378 
00379     node._geodeticRot = local2world.getRotate();
00380     //OE_INFO << LC
00381     //    << "ROT: x=" << node._geodeticRot.x() << ", y=" << node._geodeticRot.y()
00382     //    << ", z=" << node._geodeticRot.z() << ", w=" << node._geodeticRot.w()
00383     //    << std::endl;
00384 
00385     return node;
00386 }
00387 
00388 osg::BoundingSphere
00389 CubeManifold::initialBound() const
00390 {
00391     return osg::BoundingSphere( osg::Vec3d(0,0,0), _ellipsoid->getRadiusEquator() * 1.2 );
00392     //return osg::BoundingSphere( osg::Vec3d(0,0,0), 2.0 );
00393 }
00394 
00395 void
00396 CubeManifold::seed( Level maxLevel )
00397 {
00398     for( unsigned short e=0; e<12; ++e )
00399     {
00400         _ed[e]->seed( maxLevel );
00401     }
00402 }
00403 
00404 void
00405 CubeManifold::cull( osgUtil::CullVisitor* cv )
00406 {
00407     for( unsigned short e=0; e<12; ++e )
00408     {
00409         _ed[e]->cull( cv );
00410     }
00411 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines