osgEarth 2.1.1
|
00001 /* -*-c++-*- */ 00002 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph 00003 * Copyright 2008-2009 Pelican Ventures, Inc. 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 "GeodeticManifold" 00020 #include <osgEarth/Registry> 00021 00022 #define LC "[osgEarth::GeodeticManifold] " 00023 00024 GeodeticManifold::GeodeticManifold() 00025 { 00026 _profile = osgEarth::Registry::instance()->getGlobalGeodeticProfile(); 00027 _ellipsoid = _profile->getSRS()->getGeographicSRS()->getEllipsoid(); 00028 } 00029 00030 void 00031 GeodeticManifold::initialize( MeshManager* mesh ) 00032 { 00033 mesh->_minGeomLevel = 1; 00034 mesh->_minActiveLevel = 3; 00035 00036 // Construct the "vertex diamonds". 00037 _vd[0] = new Diamond(mesh, TileKey(), 0, "vd0"); // north pole 1 00038 _vd[0]->setCoord( -90, 90, 0 ); 00039 00040 _vd[1] = new Diamond(mesh, TileKey(), 0, "vd1"); // north pole 2 00041 _vd[1]->setCoord( 90, 90, 0 ); 00042 00043 _vd[2] = new Diamond(mesh, TileKey(), 0, "vd2"); // south pole 1 00044 _vd[2]->setCoord( -90, -90, 0 ); 00045 00046 _vd[3] = new Diamond(mesh, TileKey(), 0, "vd3"); // south pole 2 00047 _vd[3]->setCoord( 90, -90, 0 ); 00048 00049 _vd[4] = new Diamond(mesh, TileKey(), 0, "vd4"); 00050 _vd[4]->setCoord( -180, 0, 0 ); 00051 00052 _vd[5] = new Diamond(mesh, TileKey(), 0, "vd5"); 00053 _vd[5]->setCoord( 0, 0, 0 ); 00054 00055 // The 4 "face diamonds": 00056 _fd[0] = new Diamond(mesh, TileKey(), 0, "fd0"); 00057 _fd[0]->setCoord( -90, 0, 0 ); 00058 _fd[0]->_a[GDPARENT] = _vd[0].get(); 00059 _fd[0]->_a[QUADTREE] = _vd[2].get(); 00060 _fd[0]->_a[PARENT_L] = _vd[4].get(); 00061 _fd[0]->_a[PARENT_R] = _vd[5].get(); 00062 00063 _fd[1] = new Diamond(mesh, TileKey(), 0, "fd1"); 00064 _fd[1]->setCoord( 90, 0, 0 ); 00065 _fd[1]->_a[GDPARENT] = _vd[3].get(); 00066 _fd[1]->_a[QUADTREE] = _vd[1].get(); 00067 _fd[1]->_a[PARENT_L] = _vd[4].get(); 00068 _fd[1]->_a[PARENT_R] = _vd[5].get(); 00069 00070 _fd[2] = new Diamond(mesh, TileKey(), 0, "fd2"); // virtual north pole diamond 00071 _fd[2]->setCoord( 0, 90, 0 ); 00072 _fd[2]->_a[GDPARENT] = _vd[0].get(); 00073 _fd[2]->_a[QUADTREE] = _vd[1].get(); 00074 _fd[2]->_a[PARENT_L] = _vd[5].get(); 00075 _fd[2]->_a[PARENT_R] = _vd[4].get(); 00076 00077 _fd[3] = new Diamond(mesh, TileKey(), 0, "fd3"); // virtual south pole diamond 00078 _fd[3]->setCoord( 0, -90, 0 ); 00079 _fd[3]->_a[GDPARENT] = _vd[3].get(); 00080 _fd[3]->_a[QUADTREE] = _vd[2].get(); 00081 _fd[3]->_a[PARENT_L] = _vd[5].get(); 00082 _fd[3]->_a[PARENT_R] = _vd[4].get(); 00083 00084 // the 8 "edge diamonds" (first with geometry) 00085 _ed[0] = new Diamond(mesh, TileKey(1,0,0,_profile.get()), 1, "ed0"); 00086 _ed[0]->setCoord( -135, 45, 0 ); 00087 _ed[0]->_a[GDPARENT] = _vd[0].get(); 00088 _ed[0]->_a[QUADTREE] = _vd[4].get(); 00089 _ed[0]->_a[PARENT_L] = _fd[2].get(); 00090 _ed[0]->_a[PARENT_R] = _fd[0].get(); 00091 _ed[0]->_orientation = 0; 00092 00093 _ed[1] = new Diamond(mesh, TileKey(1,1,0,_profile.get()), 1, "ed1"); 00094 _ed[1]->setCoord( -45, 45, 0 ); 00095 _ed[1]->_a[GDPARENT] = _vd[0].get(); 00096 _ed[1]->_a[QUADTREE] = _vd[5].get(); 00097 _ed[1]->_a[PARENT_L] = _fd[0].get(); 00098 _ed[1]->_a[PARENT_R] = _fd[2].get(); 00099 _ed[1]->_orientation = 2; 00100 00101 _ed[2] = new Diamond(mesh, TileKey(1,0,1,_profile.get()), 1, "ed2"); 00102 _ed[2]->setCoord( -135, -45, 0 ); 00103 _ed[2]->_a[GDPARENT] = _vd[2].get(); 00104 _ed[2]->_a[QUADTREE] = _vd[4].get(); 00105 _ed[2]->_a[PARENT_L] = _fd[0].get(); 00106 _ed[2]->_a[PARENT_R] = _fd[3].get(); 00107 _ed[2]->_orientation = 6; 00108 00109 _ed[3] = new Diamond(mesh, TileKey(1,1,1,_profile.get()), 1, "ed3"); 00110 _ed[3]->setCoord( -45, -45, 0 ); 00111 _ed[3]->_a[GDPARENT] = _vd[2].get(); 00112 _ed[3]->_a[QUADTREE] = _vd[5].get(); 00113 _ed[3]->_a[PARENT_L] = _fd[3].get(); 00114 _ed[3]->_a[PARENT_R] = _fd[0].get(); 00115 _ed[3]->_orientation = 4; 00116 00117 _ed[4] = new Diamond(mesh, TileKey(1,2,0,_profile.get()), 1, "ed4"); 00118 _ed[4]->setCoord( 45, 45, 0 ); 00119 _ed[4]->_a[GDPARENT] = _vd[1].get(); 00120 _ed[4]->_a[QUADTREE] = _vd[5].get(); 00121 _ed[4]->_a[PARENT_L] = _fd[2].get(); 00122 _ed[4]->_a[PARENT_R] = _fd[1].get(); 00123 _ed[4]->_orientation = 0; 00124 00125 _ed[5] = new Diamond(mesh, TileKey(1,3,0,_profile.get()), 1, "ed5"); 00126 _ed[5]->setCoord( 135, 45, 0 ); 00127 _ed[5]->_a[GDPARENT] = _vd[1].get(); 00128 _ed[5]->_a[QUADTREE] = _vd[4].get(); 00129 _ed[5]->_a[PARENT_L] = _fd[1].get(); 00130 _ed[5]->_a[PARENT_R] = _fd[2].get(); 00131 _ed[5]->_orientation = 2; 00132 00133 _ed[6] = new Diamond(mesh, TileKey(1,2,1,_profile.get()), 1, "ed6"); 00134 _ed[6]->setCoord( 45, -45, 0 ); 00135 _ed[6]->_a[GDPARENT] = _vd[3].get(); 00136 _ed[6]->_a[QUADTREE] = _vd[5].get(); 00137 _ed[6]->_a[PARENT_L] = _fd[1].get(); 00138 _ed[6]->_a[PARENT_R] = _fd[3].get(); 00139 _ed[6]->_orientation = 6; 00140 00141 _ed[7] = new Diamond(mesh, TileKey(1,3,1,_profile.get()), 1, "ed7"); 00142 _ed[7]->setCoord( 135, -45, 0 ); 00143 _ed[7]->_a[GDPARENT] = _vd[3].get(); 00144 _ed[7]->_a[QUADTREE] = _vd[4].get(); 00145 _ed[7]->_a[PARENT_L] = _fd[3].get(); 00146 _ed[7]->_a[PARENT_R] = _fd[1].get(); 00147 _ed[7]->_orientation = 7; 00148 00149 // set child pointers: 00150 _fd[0]->setChild( 0, _ed[3].get() ); 00151 _fd[0]->setChild( 1, _ed[1].get() ); 00152 _fd[0]->setChild( 2, _ed[0].get() ); 00153 _fd[0]->setChild( 3, _ed[2].get() ); 00154 00155 _fd[1]->setChild( 0, _ed[4].get() ); 00156 _fd[1]->setChild( 1, _ed[6].get() ); 00157 _fd[1]->setChild( 2, _ed[7].get() ); 00158 _fd[1]->setChild( 3, _ed[5].get() ); 00159 00160 _fd[2]->setChild( 0, _ed[5].get() ); 00161 _fd[2]->setChild( 1, _ed[0].get() ); 00162 _fd[2]->setChild( 2, _ed[1].get() ); 00163 _fd[2]->setChild( 3, _ed[4].get() ); 00164 00165 _fd[3]->setChild( 0, _ed[2].get() ); 00166 _fd[3]->setChild( 1, _ed[7].get() ); 00167 _fd[3]->setChild( 2, _ed[6].get() ); 00168 _fd[3]->setChild( 3, _ed[3].get() ); 00169 00170 00171 // seed the bouding spheres of the manifold diamonds: 00172 for( unsigned short f=0; f<4; ++f ) 00173 _fd[f]->activate(); 00174 00175 for( unsigned short e=0; e<8; ++e ) 00176 _ed[e]->activate(); 00177 00178 // generate Level 3 (the first renderable quadtree decendants). 00179 seed( 3 ); 00180 00181 // hopefully, that's it! 00182 } 00183 00184 //osg::Vec3d 00185 //GeodeticManifold::project( const osg::Vec3d& coord ) const 00186 //{ 00187 // osg::Vec3d out; 00188 // 00189 // _ellipsoid->convertLatLongHeightToXYZ( 00190 // osg::DegreesToRadians( coord.y() ), 00191 // osg::DegreesToRadians( coord.x() ), 0, 00192 // out.x(), out.y(), out.z() ); 00193 // 00194 // return out; 00195 //} 00196 00197 osg::Vec3d 00198 GeodeticManifold::midpoint( const osg::Vec3d& p0, const osg::Vec3d& p1 ) const 00199 { 00200 //TODO account for date line crossing 00201 return (p0+p1)*0.5; 00202 } 00203 00204 //osg::Vec3d 00205 //GeodeticManifold::normal( const osg::Vec3d& vert ) const 00206 //{ 00207 // //TODO: this is spherical. adjust for ellipsoid if necessary. 00208 // osg::Vec3d n = vert; 00209 // n.normalize(); 00210 // return n; 00211 //} 00212 00213 MeshNode 00214 GeodeticManifold::createNode( const osg::Vec3d& manCoord ) const 00215 { 00216 MeshNode node; 00217 00218 node._manifoldCoord = manCoord; 00219 00220 node._geodeticCoord.set( 00221 osg::DegreesToRadians(manCoord.x()), osg::DegreesToRadians(manCoord.y()), manCoord.z() ); 00222 00223 osg::Vec3d temp; 00224 _ellipsoid->convertLatLongHeightToXYZ( 00225 node._geodeticCoord.y(), node._geodeticCoord.x(), node._geodeticCoord.z(), 00226 temp.x(), temp.y(), temp.z() ); 00227 00228 node._vertex = temp; 00229 00230 node._normal = _ellipsoid->computeLocalUpVector( 00231 temp.x(), temp.y(), temp.z() ); 00232 00233 return node; 00234 } 00235 00236 osg::BoundingSphere 00237 GeodeticManifold::initialBound() const 00238 { 00239 return osg::BoundingSphere( osg::Vec3d(0,0,0), _ellipsoid->getRadiusEquator() * 1.2 ); 00240 } 00241 00242 void 00243 GeodeticManifold::seed( Level maxLevel ) 00244 { 00245 for( unsigned short e=0; e<8; ++e ) 00246 { 00247 _ed[e]->seed( maxLevel ); 00248 } 00249 } 00250 00251 void 00252 GeodeticManifold::cull( osgUtil::CullVisitor* cv ) 00253 { 00254 for( unsigned short e=0; e<8; ++e ) 00255 { 00256 _ed[e]->cull( cv ); 00257 } 00258 }