1 /***********************************************************************
2 DEM - Class to represent digital elevation models (DEMs) as float-valued
4 Copyright (c) 2013-2016 Oliver Kreylos
6 This file is part of the Augmented Reality Sandbox (SARndbox).
8 The Augmented Reality Sandbox is free software; you can redistribute it
9 and/or modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2 of the
11 License, or (at your option) any later version.
13 The Augmented Reality Sandbox is distributed in the hope that it will be
14 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License along
19 with the Augmented Reality Sandbox; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 ***********************************************************************/
26 #include <IO/OpenFile.h>
28 #include <GL/GLContextData.h>
29 #include <GL/Extensions/GLARBTextureFloat.h>
30 #include <GL/Extensions/GLARBTextureRectangle.h>
31 #include <GL/Extensions/GLARBTextureRg.h>
32 #include <GL/Extensions/GLARBShaderObjects.h>
33 #include <Geometry/Matrix.h>
35 /******************************
36 Methods of class DEM::DataItem:
37 ******************************/
39 DEM::DataItem::DataItem(void)
40 : textureObjectId(0) {
41 /* Check for and initialize all required OpenGL extensions: */
42 GLARBTextureFloat::initExtension();
43 GLARBTextureRectangle::initExtension();
44 GLARBTextureRg::initExtension();
45 GLARBShaderObjects::initExtension();
47 /* Create the texture object: */
48 glGenTextures(1, &textureObjectId
);
51 DEM::DataItem::~DataItem(void) {
52 /* Destroy the texture object: */
53 glDeleteTextures(1, &textureObjectId
);
60 void DEM::calcMatrix(void) {
61 /* Convert the DEM transformation into a projective transformation matrix: */
62 demTransform
= PTransform(transform
);
63 PTransform::Matrix
& dtm
= demTransform
.getMatrix();
65 /* Pre-multiply the projective transformation matrix with the DEM space to DEM pixel space transformation: */
67 dem
.getMatrix()(0, 0) = Scalar(demSize
[0] - 1) / (demBox
[2] - demBox
[0]);
68 dem
.getMatrix()(0, 3) = Scalar(0.5) - Scalar(demSize
[0] - 1) / (demBox
[2] - demBox
[0]) * demBox
[0];
69 dem
.getMatrix()(1, 1) = Scalar(demSize
[1] - 1) / (demBox
[3] - demBox
[1]);
70 dem
.getMatrix()(1, 3) = Scalar(0.5) - Scalar(demSize
[1] - 1) / (demBox
[3] - demBox
[1]) * demBox
[1];
71 dem
.getMatrix()(2, 2) = Scalar(1) / verticalScale
;
72 dem
.getMatrix()(2, 3) = verticalScaleBase
- verticalScaleBase
/ verticalScale
;
73 demTransform
.leftMultiply(dem
);
75 /* Convert the full transformation to column-major OpenGL format: */
76 GLfloat
* dtmPtr
= demTransformMatrix
;
77 for(int j
= 0; j
< 4; ++j
)
78 for(int i
= 0; i
< 4; ++i
, ++dtmPtr
)
79 *dtmPtr
= GLfloat(dtm(i
, j
));
84 transform(OGTransform::identity
),
85 verticalScale(1), verticalScaleBase(0) {
86 demSize
[0] = demSize
[1] = 0;
93 void DEM::initContext(GLContextData
& contextData
) const {
94 /* Create and register a data item: */
95 DataItem
* dataItem
= new DataItem
;
96 contextData
.addDataItem(this, dataItem
);
98 /* Upload the DEM array into the texture object: */
99 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, dataItem
->textureObjectId
);
100 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
101 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
102 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB
, GL_TEXTURE_WRAP_S
, GL_CLAMP
);
103 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB
, GL_TEXTURE_WRAP_T
, GL_CLAMP
);
104 glTexImage2D(GL_TEXTURE_RECTANGLE_ARB
, 0, GL_LUMINANCE32F_ARB
, demSize
[0], demSize
[1], 0,
105 GL_LUMINANCE
, GL_FLOAT
, dem
);
106 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, 0);
109 void DEM::load(const char* demFileName
) {
110 /* Read the DEM file: */
111 IO::FilePtr demFile
= IO::openFile(demFileName
);
112 demFile
->setEndianness(Misc::LittleEndian
);
113 demFile
->read
<int>(demSize
, 2);
114 dem
= new float[demSize
[1]*demSize
[0]];
115 for(int i
= 0; i
< 4; ++i
)
116 demBox
[i
] = double(demFile
->read
<float>());
117 demFile
->read
<float>(dem
, demSize
[1]*demSize
[0]);
119 /* Update the DEM transformation: */
123 float DEM::calcAverageElevation(void) const {
124 /* Sum all elevation measurements: */
125 double elevSum
= 0.0;
126 const float* demPtr
= dem
;
127 for(int i
= demSize
[1] * demSize
[0]; i
> 0; --i
, ++demPtr
)
128 elevSum
+= double(*demPtr
);
130 /* Return the average elevation: */
131 return float(elevSum
/ double(demSize
[1] * demSize
[0]));
134 void DEM::setTransform(const OGTransform
& newTransform
, Scalar newVerticalScale
,
135 Scalar newVerticalScaleBase
) {
136 transform
= newTransform
;
137 verticalScale
= newVerticalScale
;
138 verticalScaleBase
= newVerticalScaleBase
;
140 /* Update the DEM transformation: */
144 void DEM::bindTexture(GLContextData
& contextData
) const {
145 /* Get the context data item: */
146 DataItem
* dataItem
= contextData
.retrieveDataItem
<DataItem
>(this);
148 /* Bind the DEM texture: */
149 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, dataItem
->textureObjectId
);
152 void DEM::uploadDemTransform(GLint location
) const {
153 /* Upload the matrix to OpenGL: */
154 glUniformMatrix4fvARB(location
, 1, GL_FALSE
, demTransformMatrix
);