1 /* -*-c++-*- */
2 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
3 * Copyright 2008-2009 Pelican Ventures, Inc.
4 * http://osgearth.org
5 *
6 * osgEarth is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>
18 */
19 #include "GeodeticManifold"
20 #include <osgEarth/Registry>
21
22 #define LC "[osgEarth::GeodeticManifold] "
23
GeodeticManifold()24 GeodeticManifold::GeodeticManifold()
25 {
26 _profile = osgEarth::Registry::instance()->getGlobalGeodeticProfile();
27 _ellipsoid = _profile->getSRS()->getGeographicSRS()->getEllipsoid();
28 }
29
30 void
initialize(MeshManager * mesh)31 GeodeticManifold::initialize( MeshManager* mesh )
32 {
33 mesh->_minGeomLevel = 1;
34 mesh->_minActiveLevel = 3;
35
36 // Construct the "vertex diamonds".
37 _vd[0] = new Diamond(mesh, TileKey(), 0, "vd0"); // north pole 1
38 _vd[0]->setCoord( -90, 90, 0 );
39
40 _vd[1] = new Diamond(mesh, TileKey(), 0, "vd1"); // north pole 2
41 _vd[1]->setCoord( 90, 90, 0 );
42
43 _vd[2] = new Diamond(mesh, TileKey(), 0, "vd2"); // south pole 1
44 _vd[2]->setCoord( -90, -90, 0 );
45
46 _vd[3] = new Diamond(mesh, TileKey(), 0, "vd3"); // south pole 2
47 _vd[3]->setCoord( 90, -90, 0 );
48
49 _vd[4] = new Diamond(mesh, TileKey(), 0, "vd4");
50 _vd[4]->setCoord( -180, 0, 0 );
51
52 _vd[5] = new Diamond(mesh, TileKey(), 0, "vd5");
53 _vd[5]->setCoord( 0, 0, 0 );
54
55 // The 4 "face diamonds":
56 _fd[0] = new Diamond(mesh, TileKey(), 0, "fd0");
57 _fd[0]->setCoord( -90, 0, 0 );
58 _fd[0]->_a[GDPARENT] = _vd[0].get();
59 _fd[0]->_a[QUADTREE] = _vd[2].get();
60 _fd[0]->_a[PARENT_L] = _vd[4].get();
61 _fd[0]->_a[PARENT_R] = _vd[5].get();
62
63 _fd[1] = new Diamond(mesh, TileKey(), 0, "fd1");
64 _fd[1]->setCoord( 90, 0, 0 );
65 _fd[1]->_a[GDPARENT] = _vd[3].get();
66 _fd[1]->_a[QUADTREE] = _vd[1].get();
67 _fd[1]->_a[PARENT_L] = _vd[4].get();
68 _fd[1]->_a[PARENT_R] = _vd[5].get();
69
70 _fd[2] = new Diamond(mesh, TileKey(), 0, "fd2"); // virtual north pole diamond
71 _fd[2]->setCoord( 0, 90, 0 );
72 _fd[2]->_a[GDPARENT] = _vd[0].get();
73 _fd[2]->_a[QUADTREE] = _vd[1].get();
74 _fd[2]->_a[PARENT_L] = _vd[5].get();
75 _fd[2]->_a[PARENT_R] = _vd[4].get();
76
77 _fd[3] = new Diamond(mesh, TileKey(), 0, "fd3"); // virtual south pole diamond
78 _fd[3]->setCoord( 0, -90, 0 );
79 _fd[3]->_a[GDPARENT] = _vd[3].get();
80 _fd[3]->_a[QUADTREE] = _vd[2].get();
81 _fd[3]->_a[PARENT_L] = _vd[5].get();
82 _fd[3]->_a[PARENT_R] = _vd[4].get();
83
84 // the 8 "edge diamonds" (first with geometry)
85 _ed[0] = new Diamond(mesh, TileKey(1,0,0,_profile.get()), 1, "ed0");
86 _ed[0]->setCoord( -135, 45, 0 );
87 _ed[0]->_a[GDPARENT] = _vd[0].get();
88 _ed[0]->_a[QUADTREE] = _vd[4].get();
89 _ed[0]->_a[PARENT_L] = _fd[2].get();
90 _ed[0]->_a[PARENT_R] = _fd[0].get();
91 _ed[0]->_orientation = 0;
92
93 _ed[1] = new Diamond(mesh, TileKey(1,1,0,_profile.get()), 1, "ed1");
94 _ed[1]->setCoord( -45, 45, 0 );
95 _ed[1]->_a[GDPARENT] = _vd[0].get();
96 _ed[1]->_a[QUADTREE] = _vd[5].get();
97 _ed[1]->_a[PARENT_L] = _fd[0].get();
98 _ed[1]->_a[PARENT_R] = _fd[2].get();
99 _ed[1]->_orientation = 2;
100
101 _ed[2] = new Diamond(mesh, TileKey(1,0,1,_profile.get()), 1, "ed2");
102 _ed[2]->setCoord( -135, -45, 0 );
103 _ed[2]->_a[GDPARENT] = _vd[2].get();
104 _ed[2]->_a[QUADTREE] = _vd[4].get();
105 _ed[2]->_a[PARENT_L] = _fd[0].get();
106 _ed[2]->_a[PARENT_R] = _fd[3].get();
107 _ed[2]->_orientation = 6;
108
109 _ed[3] = new Diamond(mesh, TileKey(1,1,1,_profile.get()), 1, "ed3");
110 _ed[3]->setCoord( -45, -45, 0 );
111 _ed[3]->_a[GDPARENT] = _vd[2].get();
112 _ed[3]->_a[QUADTREE] = _vd[5].get();
113 _ed[3]->_a[PARENT_L] = _fd[3].get();
114 _ed[3]->_a[PARENT_R] = _fd[0].get();
115 _ed[3]->_orientation = 4;
116
117 _ed[4] = new Diamond(mesh, TileKey(1,2,0,_profile.get()), 1, "ed4");
118 _ed[4]->setCoord( 45, 45, 0 );
119 _ed[4]->_a[GDPARENT] = _vd[1].get();
120 _ed[4]->_a[QUADTREE] = _vd[5].get();
121 _ed[4]->_a[PARENT_L] = _fd[2].get();
122 _ed[4]->_a[PARENT_R] = _fd[1].get();
123 _ed[4]->_orientation = 0;
124
125 _ed[5] = new Diamond(mesh, TileKey(1,3,0,_profile.get()), 1, "ed5");
126 _ed[5]->setCoord( 135, 45, 0 );
127 _ed[5]->_a[GDPARENT] = _vd[1].get();
128 _ed[5]->_a[QUADTREE] = _vd[4].get();
129 _ed[5]->_a[PARENT_L] = _fd[1].get();
130 _ed[5]->_a[PARENT_R] = _fd[2].get();
131 _ed[5]->_orientation = 2;
132
133 _ed[6] = new Diamond(mesh, TileKey(1,2,1,_profile.get()), 1, "ed6");
134 _ed[6]->setCoord( 45, -45, 0 );
135 _ed[6]->_a[GDPARENT] = _vd[3].get();
136 _ed[6]->_a[QUADTREE] = _vd[5].get();
137 _ed[6]->_a[PARENT_L] = _fd[1].get();
138 _ed[6]->_a[PARENT_R] = _fd[3].get();
139 _ed[6]->_orientation = 6;
140
141 _ed[7] = new Diamond(mesh, TileKey(1,3,1,_profile.get()), 1, "ed7");
142 _ed[7]->setCoord( 135, -45, 0 );
143 _ed[7]->_a[GDPARENT] = _vd[3].get();
144 _ed[7]->_a[QUADTREE] = _vd[4].get();
145 _ed[7]->_a[PARENT_L] = _fd[3].get();
146 _ed[7]->_a[PARENT_R] = _fd[1].get();
147 _ed[7]->_orientation = 7;
148
149 // set child pointers:
150 _fd[0]->setChild( 0, _ed[3].get() );
151 _fd[0]->setChild( 1, _ed[1].get() );
152 _fd[0]->setChild( 2, _ed[0].get() );
153 _fd[0]->setChild( 3, _ed[2].get() );
154
155 _fd[1]->setChild( 0, _ed[4].get() );
156 _fd[1]->setChild( 1, _ed[6].get() );
157 _fd[1]->setChild( 2, _ed[7].get() );
158 _fd[1]->setChild( 3, _ed[5].get() );
159
160 _fd[2]->setChild( 0, _ed[5].get() );
161 _fd[2]->setChild( 1, _ed[0].get() );
162 _fd[2]->setChild( 2, _ed[1].get() );
163 _fd[2]->setChild( 3, _ed[4].get() );
164
165 _fd[3]->setChild( 0, _ed[2].get() );
166 _fd[3]->setChild( 1, _ed[7].get() );
167 _fd[3]->setChild( 2, _ed[6].get() );
168 _fd[3]->setChild( 3, _ed[3].get() );
169
170
171 // seed the bouding spheres of the manifold diamonds:
172 for( unsigned short f=0; f<4; ++f )
173 _fd[f]->activate();
174
175 for( unsigned short e=0; e<8; ++e )
176 _ed[e]->activate();
177
178 // generate Level 3 (the first renderable quadtree decendants).
179 seed( 3 );
180
181 // hopefully, that's it!
182 }
183
184 //osg::Vec3d
185 //GeodeticManifold::project( const osg::Vec3d& coord ) const
186 //{
187 // osg::Vec3d out;
188 //
189 // _ellipsoid->convertLatLongHeightToXYZ(
190 // osg::DegreesToRadians( coord.y() ),
191 // osg::DegreesToRadians( coord.x() ), 0,
192 // out.x(), out.y(), out.z() );
193 //
194 // return out;
195 //}
196
197 osg::Vec3d
midpoint(const osg::Vec3d & p0,const osg::Vec3d & p1) const198 GeodeticManifold::midpoint( const osg::Vec3d& p0, const osg::Vec3d& p1 ) const
199 {
200 //TODO account for date line crossing
201 return (p0+p1)*0.5;
202 }
203
204 //osg::Vec3d
205 //GeodeticManifold::normal( const osg::Vec3d& vert ) const
206 //{
207 // //TODO: this is spherical. adjust for ellipsoid if necessary.
208 // osg::Vec3d n = vert;
209 // n.normalize();
210 // return n;
211 //}
212
213 MeshNode
createNode(const osg::Vec3d & manCoord) const214 GeodeticManifold::createNode( const osg::Vec3d& manCoord ) const
215 {
216 MeshNode node;
217
218 node._manifoldCoord = manCoord;
219
220 node._geodeticCoord.set(
221 osg::DegreesToRadians(manCoord.x()), osg::DegreesToRadians(manCoord.y()), manCoord.z() );
222
223 osg::Vec3d temp;
224 _ellipsoid->convertLatLongHeightToXYZ(
225 node._geodeticCoord.y(), node._geodeticCoord.x(), node._geodeticCoord.z(),
226 temp.x(), temp.y(), temp.z() );
227
228 node._vertex = temp;
229
230 node._normal = _ellipsoid->computeLocalUpVector(
231 temp.x(), temp.y(), temp.z() );
232
233 return node;
234 }
235
236 osg::BoundingSphere
initialBound() const237 GeodeticManifold::initialBound() const
238 {
239 return osg::BoundingSphere( osg::Vec3d(0,0,0), _ellipsoid->getRadiusEquator() * 1.2 );
240 }
241
242 void
seed(Level maxLevel)243 GeodeticManifold::seed( Level maxLevel )
244 {
245 for( unsigned short e=0; e<8; ++e )
246 {
247 _ed[e]->seed( maxLevel );
248 }
249 }
250
251 void
cull(osgUtil::CullVisitor * cv)252 GeodeticManifold::cull( osgUtil::CullVisitor* cv )
253 {
254 for( unsigned short e=0; e<8; ++e )
255 {
256 _ed[e]->cull( cv );
257 }
258 }
259