Waterflow
Visualize water in terrain
|
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 }