Mercurial > hg > forks > gldragon
view gldragon.cpp @ 79:8a56cb177711
Add dmglexts.h as depency to dmglrender.o
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Wed, 15 Jan 2020 16:59:56 +0200 |
parents | 3383e402817b |
children | 98e077d9d361 |
line wrap: on
line source
// // GLDragon - OpenGL PLY model viewer / simple benchmark // Programmed and designed by Matti 'ccr' Hämäläinen <ccr@tnsp.org> // (C) Copyright 2019 Tecnic Software productions (TNSP) // // See file "COPYING" for license information. // // Originally based on 'glxdragon' Copyright (c) 2009, Thomas Trummer // #include <SDL.h> #include "dmutil.h" #include "dmglrender.h" #include "dmply.h" /* Default settings etc. constants */ #define SET_DEF_WIDTH 1280 #define SET_DEF_HEIGHT 960 #define SET_FRAMES (180) #define SET_MAX_SHADER_SIZE (128 * 1024) /* Helpers */ bool dmInitSDL(DMSimpleRenderer &renderer, const int width, const int height, const int vsyncMode, const char *title) { int ret; std::string msg; // Attempt to initialize libSDL if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_EVENTS) != 0) { dmError("Unable to initialize SDL: %s\n", SDL_GetError()); return false; } // Part 1 of initialization if (!renderer.initRenderer1(title, width, height, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE)) return false; // Check if we want to attempt to use vsync switch (vsyncMode) { case 3: ret = SDL_GL_SetSwapInterval(-1); msg = "adaptive vsync"; break; case 2: ret = SDL_GL_SetSwapInterval(1); msg = "synchronized (vsync)"; break; case 1: ret = SDL_GL_SetSwapInterval(0); msg = "immediate (no vsync)"; break; case 0: msg = "vsync handling disabled"; ret = 0; break; default: ret = -1; msg = "INVALID VSYNC MODE"; break; } if (ret != 0) { dmError("Could not set vsync mode to %s.\n", msg.c_str()); return false; } // Part 3 of initialization if (!renderer.initRenderer2()) return false; dmMsg("VSync mode : %s\n", msg.c_str()); return true; } int main(int argc, char *argv[]) { bool exitFlag = false, pauseFlag = false, optShowHelp = false, optSetInputFilename = false, optUseShaders = false; int optWidth = SET_DEF_WIDTH, optHeight = SET_DEF_HEIGHT, optVSyncMode = 1; std::string optInputFilename = "dragon.scene", basePath; DMGLSimpleRenderer renderer; DMSimpleScene scene; int cycleTime = 0, cycleFrames = 0, totalTime = 0, totalFrames = 0; // Check commandline argument for enabling shaders for (int narg = 1; narg < argc; narg++) { char *arg = argv[narg]; if (arg[0] == '-') { char *opt = arg + 1; if ((opt[0] == '-' && opt[1] == 'h' && opt[2] == 'e') || opt[0] == '?' || (opt[0] == '-' && opt[1] == '?')) { optShowHelp = true; break; } else if (opt[0] == '-') opt++; switch (opt[0]) { case 'g': optUseShaders = true; break; case 's': case 'm': case 'v': { std::string marg; if (opt[1] == 0) { if (narg < argc) marg = std::string(argv[++narg]); else { printf("Option '%s' requires an argument.\n", opt); goto exit; } } else marg = std::string(opt + 1); switch (opt[0]) { case 's': { std::vector<std::string> mtokens = dmStrSplit(marg, "xX:"); if (mtokens.size() != 2) { printf("Option expects argument of format <width>x<height> in pixels.\n" "For example: -s 640x480\n"); goto exit; } optWidth = std::stoi(mtokens[0], 0, 0); optHeight = std::stoi(mtokens[1], 0, 0); } break; case 'v': optVSyncMode = std::stoi(marg, 0, 0); break; } } break; default: printf("Unknown option '%s'.\n", arg); goto exit; } } else { if (optSetInputFilename) { dmError("Please specify only one scene file.\n"); goto exit; } optSetInputFilename = true; optInputFilename = std::string(arg); if (optInputFilename.empty()) { dmError("Invalid input filename.\n"); goto exit; } } } if (optShowHelp) { printf( "Usage: %s [options] [<scenefile.scene>]\n" "-? Show this help\n" "-g Use GLSL shader instead of basic OpenGL lighting\n" "-s<w>x<h> Set window dimensions (default %d x %d)\n" "-v<0-3> Set vsync mode: 0 = do not attempt to set vsync mode\n" " (may be required for software rendering backends),\n" " 1 = no vsync, 2 = vsync, 3 = adaptive.\n" " Using vsync (2) will result in FPS being approximately\n" " whatever your monitor refresh rate is. The default\n" " value is 1 (no vsync).\n" "\n", argv[0], SET_DEF_WIDTH, SET_DEF_HEIGHT ); goto exit; } if (optWidth < 100 || optWidth > 8192 || optHeight < 100 || optHeight > 8192) { dmError("Invalid window width or height (%d x %d).\n", optWidth, optHeight); goto exit; } // Load the scene if (!scene.loadInfo(optInputFilename)) goto exit; if (scene.models.size() == 0) { dmError("Scenefile '%s' contains no models.\n", optInputFilename.c_str()); goto exit; } // Define a default light if none defined in scene file if (scene.lights.size() == 0) { DMLight light; // Default light scene.lights.push_back(light); } dmMsg("Loading %ld model(s) ..\n", scene.models.size()); basePath = dmGetPath(optInputFilename); dmMsg("Scene base path '%s'\n", basePath.c_str()); for (DMModel &model : scene.models) { if (!dmLoadFromPLY(model, basePath + model.modelFile)) goto exit; if (optUseShaders) { std::string fragFile = model.fragShaderFile.empty() ? "shader.frag" : basePath + model.fragShaderFile, vertFile = model.vertShaderFile.empty() ? "shader.vert" : basePath + model.vertShaderFile; if (!dmReadText(fragFile, model.fragShaderStr, SET_MAX_SHADER_SIZE) || !dmReadText(vertFile, model.vertShaderStr, SET_MAX_SHADER_SIZE)) goto exit; } } // Set shader usage renderer.useShaders = optUseShaders; // Initialize SDL + OpenGL if (!dmInitSDL(renderer, optWidth, optHeight, optVSyncMode, "GLDragon")) goto exit; // Compile shaders for scene if (!renderer.compileSceneShaders(scene)) goto exit; // Setup lights and camera renderer.setupLights(scene); renderer.setupCamera(scene.camera); // Main loop starts while (!exitFlag) { SDL_Event event; int frameStart, frameEnd, frameDelta; // Check for quit events while (SDL_PollEvent(&event)) switch (event.type) { case SDL_QUIT: exitFlag = true; break; case SDL_KEYDOWN: switch (event.key.keysym.sym) { case SDLK_SPACE: case SDLK_p: pauseFlag = !pauseFlag; break; case SDLK_ESCAPE: case SDLK_q: exitFlag = true; break; } } // Render the next frame frameStart = SDL_GetTicks(); renderer.drawScene(scene, totalTime); // Draw the current frame renderer.swapWindow(); // Rotate for 2 degrees if (!pauseFlag) renderer.animate(scene, totalTime); frameEnd = SDL_GetTicks(); // Check for errors renderer.checkErrors(); frameDelta = frameEnd - frameStart; // Return true if a full rotation was done if (!pauseFlag) { totalFrames++; cycleFrames++; cycleTime += frameDelta; totalTime += frameDelta; if (cycleFrames >= SET_FRAMES) { // Print the current frames per second printf("%d ms for %d frames = %.1lf FPS\n", cycleTime, cycleFrames, (cycleFrames * 1000.0f) / cycleTime); // Reset cycleFrames cycleFrames = 0; cycleTime = 0; } } } // Show totals printf("%d ms total for %d total frames = %.2lf FPS average\n", totalTime, totalFrames, ((double) totalFrames * 1000.0f) / (double) totalTime); exit: renderer.shutdownRenderer(); SDL_Quit(); return 0; }