Fixed bug in arcToHgt where it wrote to end of file instead of last row of file
[tecorrec.git] / geo / tcGeoImageData.cpp
blob96f3a65f73cc080b34dc28930cbac05a78741b19
1 /***************************************************************************
2 * This file is part of Tecorrec. *
3 * Copyright 2008 James Hogan <james@albanarts.com> *
4 * *
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. *
9 * *
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. *
14 * *
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 ***************************************************************************/
20 /**
21 * @file tcGeoImageData.cpp
22 * @brief Terrain image data.
25 #include "tcGeoImageData.h"
26 #include "tcChannelManager.h"
27 #include "tcChannel.h"
28 #include <glVector.h>
30 #include <ogr_spatialref.h>
32 #include <QObject>
35 * Constructors + destructor
38 /// Default constructor.
39 tcGeoImageData::tcGeoImageData()
40 : tcGeoData(tcGeoData::ImageData)
41 , m_channelManager(new tcChannelManager())
42 , m_texToGeo()
43 , m_geoToTex()
44 , m_effectiveTexToGeo()
45 , m_geoToEffectiveTex()
46 , m_sensor(0)
47 , m_name(QObject::tr("Unamed geographical image data"))
48 , m_sunDirection(0.0, 1.0, 0.0)
49 , m_channelSetup()
50 , m_effectiveNormals()
52 for (int i = 0; i < 3; ++i)
54 m_channelSetup[i] = false;
58 /// Destructor.
59 tcGeoImageData::~tcGeoImageData()
61 delete m_channelManager;
65 * Accessors
68 /// Get a name for this image data.
69 const QString& tcGeoImageData::name() const
71 return m_name;
74 /// Get the channel manager.
75 tcChannelManager* tcGeoImageData::channelManager() const
77 return m_channelManager;
80 /// Get the sun direction.
81 maths::Vector<3,float> tcGeoImageData::sunDirection(const tcGeo& coord) const
83 return (maths::Vector<3,float>)(coord.operator maths::Matrix<3,double>() * m_sunDirection);
87 * Main interface
90 /// Get the affine transformation from texture to geo.
91 const tcAffineTransform2<double> tcGeoImageData::texToGeo() const
93 return m_texToGeo;
96 /// Get the affine transformation from geo to texture.
97 const tcAffineTransform2<double> tcGeoImageData::geoToTex() const
99 return m_geoToTex;
102 /// Get the affine transformation from effective texture to geo.
103 const tcAffineTransform2<double> tcGeoImageData::effectiveTexToGeo() const
105 return m_effectiveTexToGeo;
108 /// Get the affine transformation from geo to effective texture.
109 const tcAffineTransform2<double> tcGeoImageData::geoToEffectiveTex() const
111 return m_geoToEffectiveTex;
115 * Rendering
118 void tcGeoImageData::setupThumbnailRendering(int numChannels, int* channels)
120 Q_ASSERT(numChannels >= 3);
122 float colours[3][4] = {{ 1.0f, 0.0f, 0.0f, 1.0f },
123 { 0.0f, 1.0f, 0.0f, 1.0f },
124 { 0.0f, 0.0f, 1.0f, 1.0f }};
125 for (int i = 0; i < 3; ++i)
127 if (channels[i] >= 0 && channels[i] < channelManager()->numChannels())
129 m_channelSetup[i] = true;
130 glActiveTexture(GL_TEXTURE0 + i);
131 glEnable(GL_TEXTURE_2D);
132 glBindTexture(GL_TEXTURE_2D, channelManager()->channel(channels[i])->thumbnailTexture());
133 /// @todo Do this in a non NV specific way
134 // result = previous*1 + texture*colour
135 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, colours[i]);
137 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);
138 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD);
139 if (i == 0)
141 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_ZERO);
142 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
143 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_ZERO);
144 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
146 else
148 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
149 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
150 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_ZERO);
151 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_ONE_MINUS_SRC_COLOR);
153 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_TEXTURE);
154 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR);
155 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, GL_CONSTANT);
156 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, GL_SRC_COLOR);
158 else
160 m_channelSetup[i] = false;
164 setEffectiveTexToGeo(texToGeo());
167 void tcGeoImageData::setupDetailedRendering(int numChannels, int* channels,
168 const tcGeo& swCorner, const tcGeo& neCorner)
170 Q_ASSERT(numChannels >= 3);
172 float colours[3][4] = {{ 1.0f, 0.0f, 0.0f, 1.0f },
173 { 0.0f, 1.0f, 0.0f, 1.0f },
174 { 0.0f, 0.0f, 1.0f, 1.0f }};
176 tcGeo seCorner(neCorner.lon(), swCorner.lat());
177 tcGeo nwCorner(swCorner.lon(), neCorner.lat());
178 // Translate coordinates, we don't care about innacuracies along the edges
179 maths::Vector<2,double> swTexCoord = geoToTex() * swCorner;
180 maths::Vector<2,double> neTexCoord = geoToTex() * neCorner;
181 double r1x = swTexCoord[0];
182 double r1y = neTexCoord[1];
183 double r2x = neTexCoord[0];
184 double r2y = swTexCoord[1];
186 // Load any additionals
187 for (int i = 3; i < numChannels; ++i)
189 if (channels[i] >= 0 && channels[i] < channelManager()->numChannels())
191 Reference<tcAbstractPixelData> data = channelManager()->channel(channels[i])->portion(&r1x, &r1y, &r2x, &r2y);
192 m_effectiveNormals[i-3] = dynamicCast<tcTypedPixelData<maths::Vector<3,float> >*>(data);
195 for (int i = 0; i < 3; ++i)
197 if (channels[i] >= 0 && channels[i] < channelManager()->numChannels())
199 m_channelSetup[i] = true;
200 // Only bother if we're overlapping the interesting bit
201 if (r1x < 1.0 && r1y < 1.0 && r2x > 0.0 && r2y > 0.0)
203 GLuint texture = channelManager()->channel(channels[i])->portionTexture(&r1x, &r1y, &r2x, &r2y);
204 if (0 != texture)
206 glActiveTexture(GL_TEXTURE0 + i);
207 glEnable(GL_TEXTURE_2D);
208 glBindTexture(GL_TEXTURE_2D, texture);
209 /// @todo Do this in a non NV specific way
210 // result = previous*1 + texture*colour
211 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, colours[i]);
213 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);
214 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD);
215 if (i == 0)
217 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_ZERO);
218 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
219 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_ZERO);
220 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
222 else
224 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
225 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
226 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_ZERO);
227 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_ONE_MINUS_SRC_COLOR);
229 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_TEXTURE);
230 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR);
231 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, GL_CONSTANT);
232 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, GL_SRC_COLOR);
236 else
238 m_channelSetup[i] = false;
242 setEffectiveTexToGeo(tcAffineTransform2<double>(nwCorner, seCorner-nwCorner));
245 void tcGeoImageData::setupNormalRendering()
247 for (int i = 0; i < 3; ++i)
249 glActiveTexture(GL_TEXTURE0 + i);
250 glBindTexture(GL_TEXTURE_2D, 0);
251 glDisable(GL_TEXTURE_2D);
252 m_channelSetup[i] = false;
254 glActiveTexture(GL_TEXTURE0);
257 void tcGeoImageData::texCoord(const tcGeo& coord)
259 // Coordinates need offsetting and scaling
260 maths::Vector<2,double> texCoord = geoToEffectiveTex() * coord;
261 for (int i = 0; i < 3; ++i)
263 if (m_channelSetup[i])
265 glMultiTexCoord2(GL_TEXTURE0 + i, texCoord);
270 maths::Vector<3,float> tcGeoImageData::normalAt(int norm, const tcGeo& coord)
272 Q_ASSERT(norm >= 0 && norm < 3);
273 if (0 != m_effectiveNormals[norm])
275 maths::Vector<2,double> texCoord = geoToEffectiveTex() * coord;
276 return m_effectiveNormals[norm]->interpolateLinear(texCoord[0], texCoord[1]);
278 else
280 return maths::Vector<3,float>(0.0f);
284 void tcGeoImageData::finishRendering()
286 for (int i = 0; i < 3; ++i)
288 m_effectiveNormals[i] = 0;
293 * Protected mutators
296 /// Set the texture to geo transformation.
297 void tcGeoImageData::setTexToGeo(const tcAffineTransform2<double>& texToGeo)
299 m_texToGeo = texToGeo;
300 m_geoToTex = texToGeo.inverse();
303 /// Set the effective texture to geo transformation.
304 void tcGeoImageData::setEffectiveTexToGeo(const tcAffineTransform2<double>& effectiveTexToGeo)
306 m_effectiveTexToGeo = effectiveTexToGeo;
307 m_geoToEffectiveTex = effectiveTexToGeo.inverse();
310 /// Set the name.
311 void tcGeoImageData::setName(const QString& name)
313 m_name = name;
316 /// Set the sun direction.
317 void tcGeoImageData::setSunDirection(const tcGeo& sunDirection, const tcGeo& sunReference)
319 m_sunDirection = sunReference * (maths::Vector<3,double>)sunDirection;