Waterflow
Visualize water in terrain
src/program.cpp
Go to the documentation of this file.
00001 
00002 
00003 
00004 #include "program.h"
00005 
00006 #include "GL_utilities.h"
00007 #include "voxelTesting.h"
00008 #include "gtc/type_ptr.hpp"
00009 #include <iostream>
00010 
00011 
00012 Program::Program(GLuint simCaseIn) {
00013     simCase = simCaseIn;
00014     screenW = 800;
00015     screenH = 800;
00016     
00017     sim = true;
00018 
00019     isRunning = true;
00020     mouseHidden = true;
00021 
00022     heightAtClickData = 0.0f;
00023     heighAtClickProj = 0.0f;
00024 
00025     // Time init
00026     currentTime = (GLfloat)SDL_GetTicks();
00027     deltaTime = 0;
00028     dtSim = 1.0f / (2.0f*20.0f*30.0f);
00029 }
00030 
00031 Program::~Program() {}
00032 
00033 int Program::exec() {
00034     
00035     if (!init()) return -1;
00036 
00037     SDL_Event Event;
00038     
00039     while (isRunning) {
00040         timeUpdate();
00041         while (SDL_PollEvent(&Event)) handleEvent(&Event);
00042         checkKeys();
00043         update();
00044         display();
00045     }
00046 
00047     clean();
00048     return 0;
00049 }
00050 
00051 int Program::testVoxels() {
00052 
00053     if (!init()) return -1;
00054     SDL_SetRelativeMouseMode(SDL_FALSE);
00055     voxelTest::mainTest(dataHandler);
00056     
00057     return 0;
00058 
00059 }
00060 bool Program::init() {
00061     // SDL, glew and OpenGL init
00062     if (SDL_Init(SDL_INIT_VIDEO) != 0) {
00063         fprintf(stderr, "Failed to initialise SDL: %s", SDL_GetError());
00064         return false;
00065     }
00066 
00067 #ifdef __APPLE__
00068     SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
00069     SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
00070 
00071     SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
00072 #endif
00073 
00074 
00075     screen = SDL_CreateWindow("WaterFlow", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, screenW, screenH, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
00076     if (screen == 0) {
00077         fprintf(stderr, "Failed to set Video Mode: %s", SDL_GetError());
00078         return false;
00079     }
00080 
00081 
00082     glcontext = SDL_GL_CreateContext(screen);
00083 
00084     SDL_SetRelativeMouseMode(SDL_TRUE);
00085     glClearColor(0.1f, 0.7f, 0.1f, 1.0f);
00086     printError("After SDL init: ");
00087 
00088 
00089 #ifdef _WINDOWS
00090     glewInit();
00091 #endif
00092     //Check for compatibility.
00093     int numBindings;
00094     glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &numBindings);
00095 
00096     if (simCase == 1) {
00097         if (numBindings > 8) {
00098 
00099         }
00100         else {
00101             std::cerr << "This graphics card has too few Shader Storage Buffer bindings" << std::endl;
00102             system("pause");
00103             return false;
00104         }
00105     }if (simCase == 2) {
00106         if (numBindings > 12) {
00107 
00108         }
00109         else {
00110             std::cerr << "This graphics card has too few Shader Storage Buffer bindings" << std::endl;
00111             system("pause");
00112             return false;
00113         }
00114     }
00115 
00116 
00117 
00118 
00119     dumpInfo();
00120     /* Functions below read start values and source-files form XML-file into a struct init_data-> Data from this
00121     is then used as startdata.
00122     */
00123     const char* xmlfile = "src/xml/xgconsole.xml";
00124 
00125     init_data = new init_Data_struct(xmlfile);
00126     // Load terrain data.
00127     dataHandler = new DataHandler(init_data->data_filename.c_str());
00128 
00129     // Load previous simulation
00130     heightData = new FileHandler(dataHandler->getDataWidth(), dataHandler->getDataHeight());
00131     velocityData = new FileHandler(dataHandler->getDataWidth(), dataHandler->getDataHeight());
00132 
00133     heightData->LoadData(init_data->height_load_path.c_str());
00134     velocityData->LoadData(init_data->velocity_load_path.c_str());
00135 
00136     // Initial placement of camera.
00137     int xzLim = 250; // Maximal distance (x and z) between terrain and camera
00138     int yLimLo = 100; // Minimal distance (y) between camera and terrain
00139     int yLimHi = 500; // yLimHi + dataHandler->getTerrainScale() = maximal distance (y) between camera and terrain
00140     cam = new Camera(glm::vec3(0.0f, 500.0f, 0.0f), &screenW, &screenH, dataHandler->getDataWidth(), dataHandler->getDataHeight(), xzLim, yLimLo, yLimHi, dataHandler);
00141     
00142     printError("After hf init");
00143     
00144     // Load and compile shaders.
00145     terrainshader = loadShaders("src/shaders/terrainshader.vert", "src/shaders/terrainshader.frag");
00146     skyshader = loadShaders("src/shaders/skyshader.vert", "src/shaders/skyshader.frag");
00147     depthshader = loadShaders("src/shaders/terrainshader.vert", "src/shaders/depthshader.frag");
00148     
00149     GLuint sizes[] = {(GLuint)dataHandler->getDataWidth(),(GLuint)dataHandler->getDataHeight() };       
00150         
00151     // Create drawables
00152     myDrawable::setLights();
00153     myDrawable::setTextures(sizes);
00154 
00155     if (simCase == 1) {
00156         terrain = new HeightMap(terrainshader, sizes, dataHandler->getTerrainScale(), dataHandler->getHeightBuffer());
00157         terrain->update();
00158         dynamic_cast<HeightMap*>(terrain)->generateHeightTexture();
00159         
00160         printError("Created Terrain");
00161     
00162         watershader = loadShaders("src/shaders/terrainshader.vert", "src/shaders/watershader.frag");
00163 
00164         // Initialize water simulation
00165         hf = new HeightField(dataHandler, init_data->FFData, init_data->Flowsources);
00166         hf->initGPU(heightData->GetArray(), velocityData->GetArray());
00167 
00168         GLuint shaders[2] = { watershader, depthshader };
00169         waterTerrain = new Water(shaders, sizes, dataHandler->getTerrainScale(), hf->fieldBuffers[0]);
00170     } else if(simCase == 2) {
00171         terrain = new HeightMap(terrainshader, sizes, -1.0f, dataHandler->getHeightBuffer());
00172         terrain->update();
00173         dynamic_cast<HeightMap*>(terrain)->generateHeightTexture();
00174         
00175         printError("Created Terrain");
00176     
00177         watershader = loadShaders("src/shaders/terrainshader.vert", "src/shaders/shallowwatershader.frag");
00178         cam->unlock();
00179 
00180         // Initialize water simulation
00181         sgpu = new ShallowGPU(dataHandler, init_data->FFData);
00182         sgpu->initGPU();
00183 
00184         GLuint shaders[2] = { watershader, depthshader };
00185         waterTerrain = new Water(shaders, sizes, dataHandler->getTerrainScale(), sgpu->shallowBuffers[7]);
00186     }
00187         
00188     printError("Created Water");
00189     skycube = new SkyCube(skyshader);
00190 
00191 
00192     /* Initialize AntTweakBar */
00193     TwInit(TW_OPENGL_CORE, NULL);
00194     TwWindowSize(screenW, screenH);
00195     antBar = TwNewBar("UIinfo");
00196     TwDefine(" UIinfo refresh=0.1 ");
00197     TwDefine(" UIinfo valueswidth=fit ");
00198     TwDefine(" UIinfo size='280 350' ");
00199     TwAddVarRO(antBar, "FPS", TW_TYPE_FLOAT, &FPS, "group=Info");
00200     TwAddVarRO(antBar, "CameraX", TW_TYPE_FLOAT, &cam->getPos()->x, "group=Info");
00201     TwAddVarRO(antBar, "CameraZ", TW_TYPE_FLOAT, &cam->getPos()->z, "group=Info");
00202 
00203     TwAddVarRO(antBar, "Camera Height", TW_TYPE_FLOAT, &cam->getPos()->y, "group=Info");
00204     TwAddVarRO(antBar, "TerrainHeightCamera", TW_TYPE_FLOAT, &heightAtPos, " label='Terrain Height' help= 'Shows terrain height at camera position' group=Info");
00205 
00206     TwAddVarRO(antBar, "Water Depth", TW_TYPE_FLOAT, &heighAtClickProj, "group=Click help= 'Shows water depth at click using inverse projection' ");
00207     TwAddVarRO(antBar, "Terrain Height", TW_TYPE_FLOAT, &heightAtClickData, "group=Click help= 'Shows terrain height at click using terrain data for height' ");
00208     TwAddVarRO(antBar, "Terrain X", TW_TYPE_DOUBLE, &objX, "group=Click help= 'Shows terrain x at click' ");
00209     TwAddVarRO(antBar, "Terrain Z", TW_TYPE_DOUBLE, &objZ, "group=Click help= 'Shows terrain z at click' ");
00210 
00211     TwAddVarRW(antBar, "MovSpeed", TW_TYPE_FLOAT, cam->getSpeedPtr(), " min=0 max=10 step=0.05 group=Changables label='Movement speed' ");
00212     TwAddVarRW(antBar, "RotSpeed", TW_TYPE_FLOAT, cam->getRotSpeedPtr(), " min=0 max=0.1 step=0.0005 group=Changables label='Rotation speed' ");
00213 
00214     TwAddVarCB(antBar, "Terrain Texture", TW_TYPE_INT32, HeightMap::SetTextureCB, HeightMap::GetTextureCB, terrain, " min=0 max=2 step=1 group=Changables ");
00215     TwAddVarCB(antBar, "Bottom Texture", TW_TYPE_INT32, HeightMap::SetTextureCB, HeightMap::GetTextureCB, waterTerrain, " min=0 max=2 step=1 group=Changables ");
00216 
00217     TwAddVarCB(antBar, "Draw Program", TW_TYPE_INT32, Water::SetDrawProgramCB, Water::GetDrawProgramCB, waterTerrain, " min=0 max=1 step=1 group=Changables ");
00218     TwAddVarCB(antBar, "Transparency", TW_TYPE_FLOAT, Water::SetTransparencyCB, Water::GetTransparencyCB, waterTerrain, " min=0 max=1.0 step=0.05 group=Changables ");
00219     TwAddVarCB(antBar, "MaxDepth", TW_TYPE_FLOAT, Water::SetMaxDepthCB, Water::GetMaxDepthCB, waterTerrain, " min=0 max=500.0 step=10.0 group=Changables ");
00220     TwAddVarRW(antBar, "Simulation dt", TW_TYPE_FLOAT, &dtSim, "min=0.00005 max=0.0025 step=0.00005 group=Changables label='Simulation dt' ");
00221     
00222     printError("After total init: ");
00223 
00224     return true;
00225 }
00226 
00227 void Program::timeUpdate() {
00228     GLfloat t = (GLfloat)SDL_GetTicks();
00229     deltaTime = t - currentTime;
00230     currentTime = t;
00231     FPS = 1000.0f / deltaTime;
00232 }
00233 
00234 void Program::update() {
00235     // Update the tweak bar.
00236     heightAtPos = dataHandler->giveHeight(cam->getPos()->x, cam->getPos()->z);
00237         
00238     
00239     if (simCase == 1)
00240     {
00241         
00242         if (sim) {
00243             hf->runSimGPU(dtSim);
00244         }
00245     
00246     
00247     
00248     }else if(simCase == 2)
00249     {
00250         if (sim) {
00251             sgpu->runSimGPU();
00252         }
00253     }
00254     
00255     
00256     waterTerrain->update();
00257 
00258 }
00259 
00260 
00261 void Program::display() {
00262     // Clear the screen.
00263     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00264 
00265     // ========================== Draw skybox ==========================
00266     glDisable(GL_CULL_FACE);
00267     glDisable(GL_DEPTH_TEST);
00268 
00269     // ---Camera shader data---
00270     cam->uploadCamData(skyshader);
00271     skycube->draw();
00272 
00273     // ========================== Draw Terrain =========================
00274     glEnable(GL_DEPTH_TEST);
00275     glEnable(GL_CULL_FACE);
00276     glCullFace(GL_BACK);
00277 
00278     // ---Camera shader data---
00279     cam->uploadCamData(terrainshader);
00280     if(simCase != 2){
00281         terrain->draw();
00282     }
00283 
00284     // ======================== Draw water body ========================
00285     glDisable(GL_CULL_FACE);
00286 
00287     cam->uploadCamData(depthshader);
00288     cam->uploadCamData(watershader);
00289     glUniform1f(glGetUniformLocation(watershader, "time"), currentTime / 20.0f);
00290     waterTerrain->draw();
00291 
00292     // ========================== Draw AntBar ==========================
00293     TwDraw();
00294 
00295     printError("after display");
00296 
00297     SDL_GL_SwapWindow(screen);
00298 }
00299 
00300 void Program::clean() {
00301     TwTerminate();
00302     SDL_GL_DeleteContext(glcontext);
00303     SDL_Quit();
00304 }
00305 
00306 
00307 // Handle events.
00308 void Program::handleEvent(SDL_Event* event) {
00309     switch (event->type) {
00310     case SDL_QUIT:
00311         isRunning = false;
00312         break;
00313     case SDL_KEYDOWN:
00314         handleKeypress(event);
00315         break;
00316     case SDL_WINDOWEVENT:
00317         switch (event->window.event) {
00318         case SDL_WINDOWEVENT_RESIZED:
00319             SDL_SetWindowSize(screen, event->window.data1, event->window.data2);
00320             SDL_GetWindowSize(screen, &screenW, &screenH);
00321             glViewport(0, 0, screenW, screenH);
00322             TwWindowSize(screenW, screenH);
00323             cam->updateVTP();
00324             break;
00325         }
00326         break;
00327     case SDL_MOUSEMOTION:
00328         handleMouseMove(event);
00329         break;
00330     case SDL_MOUSEBUTTONDOWN:
00331         TwMouseButton(TW_MOUSE_PRESSED, TW_MOUSE_LEFT);
00332         handleMouseButton(event);
00333         break;
00334     case SDL_MOUSEBUTTONUP:
00335         TwMouseButton(TW_MOUSE_RELEASED, TW_MOUSE_LEFT);
00336         break;
00337     default:
00338         break;
00339     }
00340 }
00341 
00342 // Handle keys.
00343 void Program::handleKeypress(SDL_Event* event) {
00344     TwKeyPressed(event->key.keysym.sym, TW_KMOD_NONE);
00345     switch (event->key.keysym.sym) {
00346     case SDLK_ESCAPE:
00347         isRunning = false;
00348         break;
00349     case SDLK_h:
00350         cam->toggleFrozen();
00351         mouseHidden = !mouseHidden;
00352         if (!mouseHidden) {
00353             SDL_SetRelativeMouseMode(SDL_FALSE);
00354         } else {
00355             SDL_SetRelativeMouseMode(SDL_TRUE);
00356         }
00357         break;
00358     case SDLK_r:
00359         int isBarHidden;
00360         TwGetParam(antBar, NULL, "iconified", TW_PARAM_INT32, 1, &isBarHidden);
00361         if (!isBarHidden) {
00362             TwDefine(" UIinfo iconified=true");
00363         } else {
00364             TwDefine(" UIinfo iconified=false");
00365         }
00366         break;
00367         
00368     case SDLK_k:
00369         if(simCase == 1){
00370             hf->saveData(heightData->GetArray(),velocityData->GetArray());
00371             heightData->SaveData(init_data->height_save_path.c_str()); 
00372             velocityData->SaveData(init_data->velocity_save_path.c_str()); 
00373             
00374         }
00375         break;
00376     case SDLK_p:
00377         sim = !sim;
00378         break;
00379     case SDLK_c:
00380         if (simCase != 2)
00381             break;
00382         sgpu->cycleBuffer();
00383         break;
00384     default:
00385         break;
00386     }
00387 }
00388 
00389 void Program::handleMouseMove(SDL_Event* event) {
00390     if (!mouseHidden) {
00391         TwMouseMotion(event->motion.x, event->motion.y);
00392     }
00393     cam->changeLookAtPos(event->motion.xrel, event->motion.yrel);
00394 }
00395 
00396 void Program::handleMouseButton(SDL_Event* event) {
00397     const Uint8 *keystate = SDL_GetKeyboardState(NULL);
00398     if (keystate[SDL_SCANCODE_LSHIFT] && !mouseHidden) {
00399         float depth;
00400         int x;
00401         int y;
00402         GLint viewport[4] = { 0, 0, 0, 0 };
00403         glGetIntegerv(GL_VIEWPORT, viewport);
00404         SDL_GetMouseState(&x, &y);
00405         glReadPixels(x, viewport[3] - y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
00406         GLdouble objY = 0.0;
00407         gluUnProject((GLdouble)x, (GLdouble)(viewport[3] - y), (GLdouble)depth, glm::value_ptr((glm::dmat4)*cam->getWTV()), glm::value_ptr((glm::dmat4)*cam->getVTP()), viewport, &objX, &objY, &objZ);
00408 
00409         heightAtClickData = dataHandler->giveHeight((GLfloat)objX, (GLfloat)objZ);
00410         heighAtClickProj = fmax((GLfloat)objY - heightAtClickData, 0.0f);
00411     }
00412 }
00413 
00414 void Program::checkKeys() {
00415     const Uint8 *keystate = SDL_GetKeyboardState(NULL);
00416     if (keystate[SDL_SCANCODE_W]) {
00417         cam->forward(deltaTime);
00418     } else if (keystate[SDL_SCANCODE_S]) {
00419         cam->forward(-deltaTime);
00420     }
00421     if (keystate[SDL_SCANCODE_A]) {
00422         cam->strafe(deltaTime);
00423     } else if (keystate[SDL_SCANCODE_D]) {
00424         cam->strafe(-deltaTime);
00425     }
00426     if (keystate[SDL_SCANCODE_Q]) {
00427         cam->jump(deltaTime);
00428     } else if (keystate[SDL_SCANCODE_E]) {
00429         cam->jump(-deltaTime);
00430     }
00431 }
 All Classes Files Functions Variables Enumerations