1 /***************************************************************************
2 * This file is part of Tecorrec. *
3 * Copyright 2008 James Hogan <james@albanarts.com> *
5 * Tecorrec is free software: you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation, either version 2 of the License, or *
8 * (at your option) any later version. *
10 * Tecorrec is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with Tecorrec. If not, write to the Free Software Foundation, *
17 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
18 ***************************************************************************/
22 * @brief Manages data for a globe.
26 #include "tcPhotographyData.h"
27 #include "tcLandsatData.h"
28 #include "tcSrtmModel.h"
37 * Constructors + destructor
40 /// Primary constructor.
41 tcGlobe::tcGlobe(double meanRadius
)
42 : m_meanRadius(meanRadius
)
43 , m_elevation(new tcSrtmModel())
45 , m_elevationMode(RawElevation
)
46 , m_elevationCorrection(0.0f
)
48 addDataSet(new tcLandsatData("/home/james/cs/pro/data/LE71950281999206EDC01/"));
60 /// Add a dataset to the globe.
61 void tcGlobe::addDataSet(tcPhotographyData
* data
)
63 m_data
.push_back(data
);
70 /// Draw a line of latitude.
71 void tcGlobe::drawLineOfLatitude(double latitude
) const
73 double z
= sin(latitude
) * m_meanRadius
;
74 double xy
= cos(latitude
) * m_meanRadius
;
75 glBegin(GL_LINE_LOOP
);
77 for (int lon
= 0; lon
< 360; ++lon
)
79 glVertex3d(xy
*sin(M_PI
/180*lon
), xy
*cos(M_PI
/180*lon
), z
);
86 void tcGlobe::renderCell(tcObserver
* const observer
, const tcGeo
& swCorner
, const tcGeo
& neCorner
) const
88 // Find the square distances to each corner
90 glGetv(GL_MODELVIEW_MATRIX
, &modelview
);
91 tcGeo geoCorners
[4] = {
92 tcGeo(swCorner
.lon(), swCorner
.lat()),
93 tcGeo(swCorner
.lon(), neCorner
.lat()),
94 tcGeo(neCorner
.lon(), neCorner
.lat()),
95 tcGeo(neCorner
.lon(), swCorner
.lat())
97 GLvec3d cartCorners
[4];
99 for (int i
= 0; i
< 4; ++i
)
101 cartCorners
[i
] = (GLvec3d
)geoCorners
[i
] * m_meanRadius
;
102 toCorners
[i
] = (modelview
*(cartCorners
[i
], 1.0)).slice
<0,3>().sqr();
103 // Cull faces which are roughly backfacing
104 if ((modelview
*(cartCorners
[i
], 0.0))[2] <= 0.0)
110 // Decide whether to subdivide
111 float diagonal
= (cartCorners
[0]-cartCorners
[2]).sqr()*4;
112 bool subdivide
= true;
113 // If it is disproportionately tall, only subdivide horizontally
114 bool tall
= (cartCorners
[1] - cartCorners
[0]) > (cartCorners
[3] - cartCorners
[0]).sqr()*4.0;
115 for (int i
= 0; i
< 4; ++i
)
117 if (toCorners
[i
] > diagonal
)
126 glColor3f(0.0f
, 0.0f
, 1.0f
);
130 glColor3f(1.0f
, 0.5f
, 0.0f
);
134 glBegin(GL_LINE_LOOP
);
135 for (int i
= 0; i
< 4; ++i
)
137 glVertex3(cartCorners
[i
]);
147 renderCell(observer
, geoCorners
[0], (geoCorners
[3] + geoCorners
[2]) * 0.5);
149 renderCell(observer
, (geoCorners
[0] + geoCorners
[1]) * 0.5, geoCorners
[2]);
154 renderCell(observer
, geoCorners
[0], (geoCorners
[0] + geoCorners
[2]) * 0.5);
156 renderCell(observer
, (geoCorners
[0] + geoCorners
[3]) * 0.5, (geoCorners
[3] + geoCorners
[2]) * 0.5);
158 renderCell(observer
, (geoCorners
[0] + geoCorners
[1]) * 0.5, (geoCorners
[1] + geoCorners
[2]) * 0.5);
160 renderCell(observer
, (geoCorners
[0] + geoCorners
[2]) * 0.5, geoCorners
[2]);
166 const int resolution
= 32;
167 for (int i
= 0; i
< resolution
; ++i
)
169 glBegin(GL_TRIANGLE_STRIP
);
171 for (int j
= 0; j
<= resolution
; ++j
)
173 for (int k
= 0; k
< 2; ++k
)
175 double dlon
= (neCorner
.lon()-swCorner
.lon()) / resolution
;
176 double dlat
= (neCorner
.lat()-swCorner
.lat()) / resolution
;
177 tcGeo coord
= swCorner
+ tcGeo((i
+k
) * dlon
, j
* dlat
);
178 bool accurate
= true;
180 switch (m_elevationMode
)
185 m_elevation
->altitudeAt(coord
, true, &accurate
);
190 alt
= m_elevation
->altitudeAt(coord
, false, &accurate
);
197 case CorrectedElevation
:
200 m_elevation
->altitudeAt(coord
, true, &accurate
);
201 if (m_elevationCorrection
<= 0.0f
)
203 alt
= m_elevation
->altitudeAt(coord
, false, 0);
205 else if (m_elevationCorrection
>= 1.0f
)
207 alt
= m_elevation
->altitudeAt(coord
, true, 0);
211 double alt1
= m_elevation
->altitudeAt(coord
, false, 0);
212 double alt2
= m_elevation
->altitudeAt(coord
, true, 0);
213 alt
= alt1
*(1.0-m_elevationCorrection
) + alt2
*m_elevationCorrection
;
222 float intensity
= 0.0;
223 foreach (tcPhotographyData
* data
, m_data
)
225 intensity
+= data
->sampleIntensity(coord
);
230 glColor4f(intensity
, intensity
, intensity
, 0.5f
);
234 glColor4f(intensity
, intensity
, intensity
, 1.0f
);
235 //glColor4f(1.0f, 1.0f-(float)alt/3278.0f, 0.0f, 1.0f);
238 double rad
= m_meanRadius
+ alt
;
239 glVertex3(dir
* rad
);
247 /// Render from the POV of an observer.
248 void tcGlobe::render(tcObserver
* const observer
)
250 /// @todo use a really simple fragment shader to cull backfacing lines
253 glColor3f(0.0f
, 1.0f
, 0.0f
);
254 for (int lat
= -75; lat
<= 75; lat
+= 15)
258 drawLineOfLatitude(M_PI
/180*lat
);
262 double tropic
= (23.0 + 26.0/60 + 22.0/3600) * M_PI
/180;
264 glColor3f(1.0f
, 0.0f
, 0.0f
);
265 drawLineOfLatitude(0.0);
266 // Tropics (Capricorn and Cancer)
267 glColor3f(1.0f
, 0.0f
, 1.0f
);
268 drawLineOfLatitude(-tropic
);
269 glColor3f(1.0f
, 1.0f
, 0.0f
);
270 drawLineOfLatitude(+tropic
);
271 // Arctic and Antarctic Circles
272 glColor3f(1.0f
, 1.0f
, 1.0f
);
273 drawLineOfLatitude(+M_PI
/2 - tropic
);
274 drawLineOfLatitude(-M_PI
/2 + tropic
);
276 // Lines of longitude
277 for (int lon
= 0; lon
< 360; lon
+= 15)
279 double x
= sin(M_PI
/180*lon
) * m_meanRadius
;
280 double y
= -cos(M_PI
/180*lon
) * m_meanRadius
;
286 glColor3f(1.0f
, lon
/180, 0.0f
);
293 glBegin(GL_LINE_STRIP
);
295 for (int lat
= minLat
; lat
<= maxLat
; ++lat
)
297 double z
= cos(M_PI
/180*lat
) * m_meanRadius
;
298 double xy
= sin(M_PI
/180*lat
);
299 glVertex3d(xy
*x
, xy
*y
, z
);
306 glColor3f(0.0f
, 1.0f
, 0.0f
);
311 // Draw data diagramatically
312 foreach (tcPhotographyData
* data
, m_data
)
314 data
->renderSchematic(m_meanRadius
, observer
);
320 for (int lon
= -180; lon
< 180; lon
+= dlon
)
322 for (int lat
= -90; lat
< 90; lat
+= dlat
)
324 tcGeo
sw(M_PI
/180 * (lon
), M_PI
/180 * (lat
));
325 tcGeo
ne(M_PI
/180 * (lon
+dlon
), M_PI
/180 * (lat
+dlat
));
326 renderCell(observer
, sw
, ne
);
331 /// Set the elevation mode to render in.
332 void tcGlobe::setElevationMode(ElevationMode mode
)
334 m_elevationMode
= mode
;
337 /// Set the level of correction to show.
338 void tcGlobe::setElevationCorrection(float correction
)
340 m_elevationCorrection
= correction
;
347 /// Get the mean radius.
348 double tcGlobe::meanRadius() const