temp commit
[SARndbox.git] / DEM.cpp
blobff44382acdf39cf2e02a5493582ac1a0158e9d62
1 /***********************************************************************
2 DEM - Class to represent digital elevation models (DEMs) as float-valued
3 texture objects.
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 ***********************************************************************/
23 #include "DEM.h"
25 #include <IO/File.h>
26 #include <IO/OpenFile.h>
27 #include <GL/gl.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);
56 /********************
57 Methods of class DEM:
58 ********************/
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: */
66 PTransform dem;
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));
82 DEM::DEM(void)
83 : dem(0),
84 transform(OGTransform::identity),
85 verticalScale(1), verticalScaleBase(0) {
86 demSize[0] = demSize[1] = 0;
89 DEM::~DEM(void) {
90 delete[] dem;
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: */
120 calcMatrix();
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: */
141 calcMatrix();
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);