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 ***************************************************************************/
21 * @file tcGeoImageData.cpp
22 * @brief Terrain image data.
25 #include "tcGeoImageData.h"
26 #include "tcChannelManager.h"
27 #include "tcChannel.h"
30 #include <ogr_spatialref.h>
35 * Constructors + destructor
38 /// Default constructor.
39 tcGeoImageData::tcGeoImageData()
40 : tcGeoData(tcGeoData::ImageData
)
41 , m_channelManager(new tcChannelManager())
44 , m_effectiveTexToGeo()
45 , m_geoToEffectiveTex()
47 , m_name(QObject::tr("Unamed geographical image data"))
48 , m_sunDirection(0.0, 1.0, 0.0)
50 , m_effectiveNormals()
52 for (int i
= 0; i
< 3; ++i
)
54 m_channelSetup
[i
] = false;
59 tcGeoImageData::~tcGeoImageData()
61 delete m_channelManager
;
68 /// Get a name for this image data.
69 const QString
& tcGeoImageData::name() const
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
);
90 /// Get the affine transformation from texture to geo.
91 const tcAffineTransform2
<double> tcGeoImageData::texToGeo() const
96 /// Get the affine transformation from geo to texture.
97 const tcAffineTransform2
<double> tcGeoImageData::geoToTex() const
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
;
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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]);
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;
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();
311 void tcGeoImageData::setName(const QString
& 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
;