Waterflow
Visualize water in terrain
src/readData.cpp
Go to the documentation of this file.
00001 
00002 
00003 #include <chrono>
00004 #include "readData.h"
00005 
00006 #include "Utilities.h"
00007 #include "GL_utilities.h"
00008 
00009 #include "glm.hpp"
00010 
00011 #include <iostream>
00012 
00013 // ===== Constructors and destructors
00014 
00015 DataHandler::DataHandler(const char* inputfile) {
00016     readdata = new mapdata();
00017 
00018     std::cout << "Reading DEM data from: " << inputfile << "...";
00019     readDEM(inputfile);
00020     std::cout << " done!" << std::endl;
00021 
00022     std::cout << "Performing normalized convolution...";
00023     normConvCompute();
00024     std::cout << " done!" << std::endl;
00025 }
00026 
00027 DataHandler::~DataHandler() {
00028     delete readdata;
00029 }
00030 
00031 // ===== Getters =====
00032 
00033 float DataHandler::getCoord(int col, int row) {
00034     int index;
00035     float retdata = 0;
00036 
00037     if (readdata != NULL) {
00038 
00039         if (col < readdata->ncols && row < readdata->nrows) {
00040             index = col + row * readdata->ncols;
00041         } else {
00042             std::cerr << "Input does not exist in data. Col: " << col << " Row: " << row << std::endl;
00043             index = 0;
00044         }
00045         retdata = readdata->data[index];
00046     } else {
00047         std::cerr << "No mapdata exists." << std::endl;
00048     }
00049 
00050     return retdata;
00051 }
00052 
00053 GLfloat DataHandler::giveHeight(GLfloat x, GLfloat z) // Returns the height of a height map.
00054 {
00055     int width = getDataWidth();
00056     int height = getDataHeight();
00057 
00058     int vertX1 = (int)floor(x);
00059     int vertZ1 = (int)floor(z);
00060 
00061     int vertX2 = (int)floor(x) + 1;
00062     int vertZ2 = (int)floor(z) + 1;
00063 
00064     int vertX3 = 0;
00065     int vertZ3 = 0;
00066 
00067     GLfloat yheight = 0;
00068 
00069     if ((vertX1 >= 0) && (vertZ1 >= 0) && (vertX2 < width) && (vertZ2 < height)) {
00070 
00071         GLfloat dist1 = vertX1 - x;
00072         GLfloat dist2 = vertZ1 - z;
00073 
00074         if (dist1 > dist2) {
00075             vertX3 = vertX1;
00076             vertZ3 = vertZ1 + 1;
00077         } else {
00078             vertX3 = vertX1 + 1;
00079             vertZ3 = vertZ1;
00080         }
00081         GLfloat vertY1 = getData()[(vertX1 + vertZ1 * width)];
00082         GLfloat vertY2 = getData()[(vertX2 + vertZ2 * width)];
00083         GLfloat vertY3 = getData()[(vertX3 + vertZ3 * width)];
00084 
00085         glm::vec3 p1 = { (float)vertX1 / (float)width, vertY1, (float)vertZ1 / (float)height };
00086         glm::vec3 p2 = { (float)vertX2 / (float)width, vertY2, (float)vertZ2 / (float)height };
00087         glm::vec3 p3 = { (float)vertX3 / (float)width, vertY3, (float)vertZ3 / (float)height };
00088 
00089         glm::vec3 planeNormal = { 0, 0, 0 };
00090 
00091         // This if/else might not be making any difference whatsoever.
00092         if (dist1 > dist2) {
00093             planeNormal = glm::normalize(glm::cross(p2 - p1, p3 - p1));
00094         } else {
00095             planeNormal = glm::normalize(glm::cross(p3 - p1, p2 - p1));
00096         }
00097 
00098         GLfloat D;
00099         D = glm::dot(planeNormal, p1);
00100 
00101         yheight = (D - planeNormal.x*x / width - planeNormal.z*z / height) / planeNormal.y;
00102     }
00103     return yheight;
00104 }
00105 
00106 // ===== Actual functions =====
00107 
00108 void DataHandler::readDEM(const char* inputfile) {
00109     char* buffer = readFile(inputfile);
00110     char* currentStr = buffer;
00111     int readChars = 0;
00112 
00113     if (buffer != NULL) {
00114         if (sscanf(currentStr, "%*s %i %n", &readdata->ncols, &readChars) != 1) std::cout << "Reading DEM error!" << std::endl;
00115         currentStr += readChars;
00116         if (sscanf(currentStr, "%*s %i %n", &readdata->nrows, &readChars) != 1) std::cout << "Reading DEM error!" << std::endl;
00117         currentStr += readChars;
00118         if (sscanf(currentStr, "%*s %f %n", &readdata->xllcorner, &readChars) != 1) std::cout << "Reading DEM error!" << std::endl;
00119         currentStr += readChars;
00120         if (sscanf(currentStr, "%*s %f %n", &readdata->yllcorner, &readChars) != 1) std::cout << "Reading DEM error!" << std::endl;
00121         currentStr += readChars;
00122         if (sscanf(currentStr, "%*s %f %n", &readdata->cellsize, &readChars) != 1) std::cout << "Reading DEM error!" << std::endl;
00123         currentStr += readChars;
00124         if (sscanf(currentStr, "%*s %f %n", &readdata->NODATA_value, &readChars) != 1) std::cout << "Reading DEM error!" << std::endl;
00125         currentStr += readChars;
00126 
00127         readdata->max_value = readdata->NODATA_value;
00128         readdata->min_value = FLT_MAX;
00129 
00130         readdata->nelem = readdata->ncols * readdata->nrows;
00131         readdata->data.resize(getElem());
00132 
00133         float incoord = 0;
00134 
00135         for (int i = 0; i < getElem(); i++) {
00136             incoord = myStrtof(currentStr, &currentStr);
00137 
00138             if (incoord > readdata->max_value) {
00139                 readdata->max_value = incoord;
00140             }
00141             if (incoord > readdata->NODATA_value + 1.0f && incoord < readdata->min_value) {
00142                 readdata->min_value = incoord;
00143             }
00144             if (incoord == readdata->NODATA_value) {
00145                 incoord = -1.0f;
00146             }
00147 
00148             readdata->data[i] = incoord;
00149         }
00150         terrainScale = readdata->max_value - readdata->min_value;
00151 
00152         free(buffer);
00153     } else {
00154         std::cerr << "Could not read file: " << inputfile << std::endl;
00155     }
00156 
00157     for (int i = 0; i < getElem(); i++) {
00158         if (readdata->data[i] > 0.0f) {
00159             readdata->data[i] -= readdata->min_value;
00160         }
00161     }
00162 
00163 }
00164 
00165 void DataHandler::normConvCompute() {
00166 
00167     GLuint normConvProgram = compileComputeShader("src/shaders/normConv.comp");
00168 
00169     glGenBuffers(1, &terrainBufferID);
00170 
00171     GLuint normBuffers[3];
00172     glGenBuffers(3, normBuffers);
00173 
00174     GLint numData = getElem();
00175     GLuint reset = 0;
00176     // read buffer height
00177     glBindBuffer(GL_SHADER_STORAGE_BUFFER, normBuffers[0]);     //What data? getData()
00178     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat)*numData, getData(), GL_STATIC_DRAW);
00179     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
00180     
00181     // write buffer height
00182     glBindBuffer(GL_SHADER_STORAGE_BUFFER, normBuffers[1]);
00183     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat)*numData, NULL, GL_STATIC_DRAW);
00184     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
00185 
00186     // Atomic counter for isNODATA
00187     glBindBuffer(GL_SHADER_STORAGE_BUFFER, normBuffers[2]);
00188     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLuint), &reset, GL_STATIC_DRAW);
00189     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
00190 
00191     printError("init NormConvCompute");
00192     
00193     glUseProgram(normConvProgram);
00194     glUniform2i(glGetUniformLocation(normConvProgram, "size"), getDataWidth(), getDataHeight());
00195 
00196     GLuint isNODATA = 1;
00197     while (isNODATA) { // Ping pong the normalized convolution until there are no more NODATA
00198         isNODATA = 0;
00199 
00200         glBindBuffersBase(GL_SHADER_STORAGE_BUFFER, 0, 3, normBuffers);
00201         glDispatchCompute((GLuint)ceil((GLfloat)getDataWidth() / 16.0f), (GLuint)ceil((GLfloat)getDataHeight() / 16.0f), 1);
00202 
00203         glBindBuffer(GL_SHADER_STORAGE_BUFFER, normBuffers[2]);
00204         glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(GLuint), &isNODATA);
00205         glClearBufferData(GL_SHADER_STORAGE_BUFFER, GL_R32UI, GL_RED, GL_UNSIGNED_INT, &reset);
00206         glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
00207 
00208         std::swap(normBuffers[0], normBuffers[1]);      
00209     }
00210 
00211     terrainBufferID = normBuffers[0];
00212     
00213     // Replace the data in readdata with data from GPU
00214     glBindBuffer(GL_SHADER_STORAGE_BUFFER, terrainBufferID);
00215     glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(GLfloat)*numData, getData());
00216     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
00217 
00218     glDeleteBuffers(2, &normBuffers[1]);
00219 
00220     printError("End NormConvCompute");
00221 }
00222 
00223 
00224 
00225 
00226 
00227 
00228 
00229 
00230 
00231 
00232 
00233 
00234 
00235 
00236 
00237 
00238 
 All Classes Files Functions Variables Enumerations