Mercurial > hg > forks > gldragon
diff glxdragon.cpp @ 21:1404dfcee7b8
More work on scenefile and model loading support.
Can now load PLY models and simple scene definition files.
Converted dragon mesh to binary PLY format.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Fri, 22 Nov 2019 03:03:52 +0200 |
parents | 294c4c7943b5 |
children | 03b86b9c2f29 |
line wrap: on
line diff
--- a/glxdragon.cpp Fri Nov 22 00:14:16 2019 +0200 +++ b/glxdragon.cpp Fri Nov 22 03:03:52 2019 +0200 @@ -33,11 +33,8 @@ #include <GL/glu.h> #include <GL/glext.h> -#include <iostream> -#include <fstream> -#include <string> -#include <vector> -#include <cstdio> +#include "dmutil.h" +#include "dmmodel.h" /* Default settings etc. constants @@ -48,19 +45,6 @@ #define SET_MAX_SHADER_SIZE (128 * 1024) -/* Structures - */ -struct Mesh -{ - int nvertices, nfaces; - - std::vector<float> vertices; - std::vector<unsigned> faces; - - GLuint id_prog, id_fs, id_vs; -}; - - /* Options */ bool optUseShaders = false; @@ -68,7 +52,6 @@ optHeight = SET_DEF_HEIGHT, optVSyncMode = 1; -std::string optModelPrefix = "dragon"; /* Globals @@ -77,6 +60,8 @@ SDL_GLContext dmGLContext = NULL; +/* Helpers + */ bool dmInitSDLGL(const int width, const int height, const char *title) { int ret; @@ -169,7 +154,6 @@ glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - // Enable back face culling glEnable(GL_CULL_FACE); @@ -179,6 +163,9 @@ // Enable the depth buffer glEnable(GL_DEPTH_TEST); + // Enable normal rescaling + glEnable(GL_RESCALE_NORMAL); + // Setup depth buffer glClearDepth(1.0f); @@ -196,14 +183,14 @@ } -void dmDrawModelVA(const Mesh &mesh) +void dmDrawModel(const DMModel &model) { int maxIndices; if (optUseShaders) { // Enable shader program - glUseProgram(mesh.id_prog); + glUseProgram(model.id_prog); } else { @@ -215,15 +202,26 @@ // Render the model glGetIntegerv(GL_MAX_ELEMENTS_INDICES, &maxIndices); - glVertexPointer(3, GL_FLOAT, 3 * 4 * 2, &mesh.vertices[0]); - glNormalPointer( GL_FLOAT, 3 * 4 * 2, &mesh.vertices[3]); + glPushMatrix(); + + // Add transforms + glScalef(model.scale.x, model.scale.y, model.scale.z); + glTranslatef(model.translate.x, model.translate.y, model.translate. z); + glRotatef(model.rotate.x, 1.0f, 0.0f, 0.0f); + glRotatef(model.rotate.y, 0.0f, 1.0f, 0.0f); + glRotatef(model.rotate.z, 0.0f, 0.0f, 1.0f); - for (int n = 0; n < mesh.nfaces; n += maxIndices) + glVertexPointer(3, GL_FLOAT, 0, &model.vertices[0]); + glNormalPointer( GL_FLOAT, 0, &model.normals[0]); + + for (int n = 0; n < model.nfaces; n += maxIndices) { - const int count = std::min(maxIndices, mesh.nfaces - n); - glDrawElements(GL_TRIANGLES, count * 3, GL_UNSIGNED_INT, &mesh.faces[n * 3]); + const int count = std::min(maxIndices, model.nfaces - n); + glDrawElements(GL_TRIANGLES, count * 3, GL_UNSIGNED_INT, &model.faces[n * 3]); } + glPopMatrix(); + // Restore if (optUseShaders) { @@ -232,7 +230,7 @@ } -void dmDrawBackground() +void dmDrawScene(const DMSimpleScene &scene) { glClear(GL_DEPTH_BUFFER_BIT); @@ -270,136 +268,10 @@ glPopMatrix(); glEnable(GL_DEPTH_TEST); -} - -bool dmReadText(const std::string &filename, std::string &buf, const int maxSize) -{ - std::ifstream in(filename.c_str()); - - if (!in.is_open()) - { - printf("ERROR: Unable to open file '%s'.\n", - filename.c_str()); - return false; - } - - in.seekg(0, std::ios::end); - - if (in.tellg() > maxSize) - { - printf("ERROR: File '%s' is too large.\n", - filename.c_str()); - return false; - } - - buf.reserve(in.tellg()); - in.seekg(0, std::ios::beg); - - buf.assign((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>()); - - return true; -} - - -bool dmLoadMesh(const std::string &filename, const std::string &infofilename, Mesh &mesh) -{ - std::ifstream info(infofilename.c_str()); - int required = 0, nline = 0; - - printf("INFO: Trying to read mesh meta from '%s'.\n", - infofilename.c_str()); - - if (!info.is_open()) - { - printf("ERROR: Unable to open file '%s'.\n", - infofilename.c_str()); - return false; - } - - while (required != 0x03) - { - std::string tmp; - int value; - char key; - - // Read one line - if (!std::getline(info, tmp)) - { - printf("ERROR: Could not read from file '%s'.\n", - infofilename.c_str()); - return false; - } - - nline++; - - // Skip empty lines and comments - if (tmp.empty() || tmp.substr(0, 1) == "#") - continue; - - if (sscanf(tmp.c_str(), "%c:%d", &key, &value) != 2) - { - printf("ERROR: Syntax error in '%s' line #%d\n'%s'\n", - infofilename.c_str(), - nline, - tmp.c_str()); - return false; - } - - switch (key) - { - case 'v': - mesh.nvertices = value; - required |= 0x01; - break; - - case 'f': - mesh.nfaces = value; - required |= 0x02; - break; - - default: - printf("ERROR: Syntax error in '%s' line #%d\nUnknown key value '%c'.\n", - infofilename.c_str(), - nline, - key); - break; - } - } - - if (mesh.nvertices < 3 || mesh.nfaces < 1) - { - printf("ERROR: Invalid nvertices (%d) and/or nfaces (%d) in '%s'.\n", - mesh.nvertices, mesh.nfaces, - infofilename.c_str()); - return false; - } - - printf("INFO: %d vertices, %d faces\n", mesh.nvertices, mesh.nfaces); - printf("INFO: Trying to read mesh data from '%s'.\n", - filename.c_str()); - - std::ifstream in(filename.c_str(), std::ios::binary); - - if (!in.is_open()) - { - printf("ERROR: Unable to open file '%s'.\n", - filename.c_str()); - return false; - } - - mesh.vertices.resize(mesh.nvertices * 6); - in.read(reinterpret_cast<char*>(&mesh.vertices[0]), mesh.nvertices * 6 * 4); - - mesh.faces.resize(mesh.nfaces * 3); - - for (int i = 0; i < mesh.nfaces; i++) - { - in.seekg(1, std::ios::cur); - in.read(reinterpret_cast<char*>(&mesh.faces[i * 3]), 3 * 4); - } - - return true; + // Draw models + for (const DMModel &model : scene.models) + dmDrawModel(model); } @@ -415,22 +287,25 @@ } -void dmLinkMeshShaders(Mesh &mesh) +void dmLinkModelShaders(DMModel &model) { - mesh.id_prog = glCreateProgram(); - glAttachShader(mesh.id_prog, mesh.id_fs); - glAttachShader(mesh.id_prog, mesh.id_vs); - glLinkProgram(mesh.id_prog); + model.id_prog = glCreateProgram(); + glAttachShader(model.id_prog, model.id_fs); + glAttachShader(model.id_prog, model.id_vs); + glLinkProgram(model.id_prog); } int main(int argc, char *argv[]) { - std::string modelVertStr, modelFragStr; - Mesh modelMesh; - bool exitFlag = false, optShowHelp = false; int startTime, cycleStart, cycleFrames = 0, totalFrames = 0; double totalTime; + bool + exitFlag = false, + optShowHelp = false, + optSetInputFilename = false; + std::string optInputFilename = "dragon.scene", basePath; + DMSimpleScene scene; // Check commandline argument for enabling shaders for (int narg = 1; narg < argc; narg++) @@ -469,7 +344,6 @@ { case 'w': optWidth = atoi(opt + 1); break; case 'h': optHeight = atoi(opt + 1); break; - case 'm': optModelPrefix = std::string(opt + 1); break; case 'v': optVSyncMode = atoi(opt + 1); break; } break; @@ -479,20 +353,36 @@ goto exit; } } + else + { + if (optSetInputFilename) + { + printf("ERROR: Please specify only one scene file.\n"); + goto exit; + } + + optSetInputFilename = true; + optInputFilename = std::string(arg); + if (optInputFilename.empty()) + { + printf("ERROR: Invalid input filename.\n"); + goto exit; + } + + } } if (optShowHelp) { printf( - "Usage: %s [options]\n" + "Usage: %s [options] [<scenefile.scene>]\n" "-? Show this help\n" "-g Use GLSL shader instead of basic OpenGL lighting\n" "-w<width> Window width (default %d)\n" "-h<height> Window height (default %d)\n" - "-m<modelfile> Set model filenames prefix. Using \"-mfoo\" will\n" - " specify \"foo.mesh\", \"foo.frag\", \"foo.vert\".\n" "-v<1-3> Set vsync mode: 1 = no vsync, 2 = vsync, 3 = adaptive\n" - " Default is no vsync.\n" + " Default is no vsync. Using vsync will result in FPS being\n" + " approx whatever your monitor refresh rate is.\n" "\n", argv[0], SET_DEF_WIDTH, SET_DEF_HEIGHT @@ -508,33 +398,53 @@ goto exit; } - if (optModelPrefix.empty()) + // Load the scene + if (!scene.loadInfo(optInputFilename)) + goto exit; + + if (scene.models.size() == 0) { - printf("Model file prefix empty.\n"); + printf("ERROR: Scenefile '%s' contains no models.\n", + optInputFilename.c_str()); goto exit; } - if (!dmLoadMesh(optModelPrefix + ".mesh", optModelPrefix + ".info", modelMesh)) - goto exit; + printf("INFO: Loading %ld model(s) ..\n", + scene.models.size()); - if (optUseShaders) + basePath = dmGetPath(optInputFilename); + printf("INFO: Model base path '%s'\n", basePath.c_str()); + + for (DMModel &model : scene.models) { - // Read shader files - if (!dmReadText(optModelPrefix + ".frag", modelFragStr, SET_MAX_SHADER_SIZE) || - !dmReadText(optModelPrefix + ".vert", modelVertStr, SET_MAX_SHADER_SIZE)) + if (!model.loadFromPLY(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; + } } // Initialize SDL + OpenGL - if (!dmInitSDLGL(optWidth, optHeight, "GLXDragon2")) + if (!dmInitSDLGL(optWidth, optHeight, "GLDragon")) goto exit; // According to our mode .. if (optUseShaders) { - modelMesh.id_fs = dmCompileShader(GL_FRAGMENT_SHADER, modelFragStr); - modelMesh.id_vs = dmCompileShader(GL_VERTEX_SHADER, modelVertStr); - dmLinkMeshShaders(modelMesh); + for (DMModel &model : scene.models) + { + model.id_fs = dmCompileShader(GL_FRAGMENT_SHADER, model.fragShaderStr); + model.id_vs = dmCompileShader(GL_VERTEX_SHADER, model.vertShaderStr); + dmLinkModelShaders(model); + } } else { @@ -591,8 +501,7 @@ } // Render the next frame - dmDrawBackground(); - dmDrawModelVA(modelMesh); + dmDrawScene(scene); // Draw the current frame SDL_GL_SwapWindow(dmWindow);