changeset 3:be31ff9e5f58

Port to libSDL2, clean up the code and some de-C++-ifications.
author Matti Hamalainen <ccr@tnsp.org>
date Sun, 27 Oct 2019 17:57:37 +0200
parents b45d8958e5a6
children 575fab206bc6
files Makefile glxdragon.cpp
diffstat 2 files changed, 129 insertions(+), 109 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Sun Oct 27 17:27:55 2019 +0200
+++ b/Makefile	Sun Oct 27 17:57:37 2019 +0200
@@ -1,11 +1,14 @@
+BINEXT = 
 
-CC      = g++
-CFLAGS  = -O2 -Wall -I/usr/include/SDL
-LDFLAGS = -lSDL -lGL -lGLU
+CFLAGS  = -O3 -W -Wall $(shell pkg-config --cflags sdl2 gl glu)
+LDFLAGS = $(shell pkg-config --libs sdl2 gl glu)
 
-glxdragon: glxdragon.cpp
-	$(CC) $(CFLAGS) -o glxdragon glxdragon.cpp $(LDFLAGS)
+TARGETS = glxdragon$(BINEXT)
+
+glxdragon$(BINEXT): glxdragon.cpp
+	$(CXX) $(CFLAGS) -o $@ $< $(LDFLAGS)
 
 clean:
-	rm glxdragon
+	$(RM) $(TARGETS)
 
+
--- a/glxdragon.cpp	Sun Oct 27 17:27:55 2019 +0200
+++ b/glxdragon.cpp	Sun Oct 27 17:57:37 2019 +0200
@@ -1,7 +1,10 @@
-
+//
 // Copyright (c) 2009, Thomas Trummer
 // All rights reserved.
 //
+// Port to libSDL2 and cleanups by Matti Hämäläinen <ccr@tnsp.org>
+// (C) Copyright 2019 Tecnic Software productions (TNSP)
+//
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are met:
 //     * Redistributions of source code must retain the above copyright
@@ -23,10 +26,11 @@
 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
+//
 
 #include <SDL.h>
 #include <SDL_opengl.h>
+#include <GL/glu.h>
 
 #include <iostream>
 #include <sstream>
@@ -39,59 +43,67 @@
 #include <ctime>
 
 
-struct Mesh
-{
-    std::vector <float>            vertices;
-    std::vector <unsigned>     faces;
-}
-dragonMesh;
+#define SET_FRAMES (180 * 2)
+
+
+SDL_Window *s_window = NULL;
+SDL_GLContext s_context;
 
 
-void init(const int windowWidth, const int windowHeight, const std::string& windowTitle)
+struct Mesh
 {
-    std::stringstream ss;
+    std::vector<float>    vertices;
+    std::vector<unsigned> faces;
+};
 
 
-    if (SDL_Init(SDL_INIT_VIDEO) != 0)
-    {
-        ss << "Unable to initialize SDL: " << SDL_GetError() << '\n';
-
-        throw std::runtime_error(ss.str());
-    }
-
-
+bool init(const int width, const int height, const char *title)
+{
     SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
     SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
     SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
     SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
     SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
 
-
-    SDL_WM_SetCaption(windowTitle.c_str(), 0);
-
+    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_EVENTS) != 0)
+    {
+        printf("ERROR: Unable to initialize SDL: %s\n",
+            SDL_GetError());
+        return false;
+    }
 
-    if ((SDL_SetVideoMode(windowWidth, windowHeight, 0, SDL_OPENGL)) == NULL)
+    if ((s_window = SDL_CreateWindow(title,
+            SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
+            width, height,
+            SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE)) == NULL)
     {
-        ss << "Couldn't set GL mode: " << SDL_GetError() << '\n';
-
-        throw std::runtime_error(ss.str());
+        printf("ERROR: Could not create SDL window: %s",
+            SDL_GetError());
+        return false;
     }
 
+    if ((s_context = SDL_GL_CreateContext(s_window)) == NULL)
+    {
+        printf("ERROR: Unable to create SDL OpenGL context: %s\n",
+            SDL_GetError());
+        return false;
+    }
 
-    std::cout << "GL_VENDOR     : " << glGetString(GL_VENDOR)     << std::endl;
-    std::cout << "GL_RENDERER : " << glGetString(GL_RENDERER) << std::endl;
-    std::cout << "GL_VERSION    : " << glGetString(GL_VERSION)    << std::endl;
-
-    std::cout << std::endl;
-
+    printf(
+        "GL_VENDOR   : %s\n"
+        "GL_RENDERER : %s\n"
+        "GL_VERSION  : %s\n",
+        glGetString(GL_VENDOR),
+        glGetString(GL_RENDERER),
+        glGetString(GL_VERSION));
 
     // Setup the window and view port
-    glViewport(0, 0, windowWidth, windowHeight);
+    glViewport(0, 0, width, height);
 
     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
 
-    gluPerspective(45.0f, GLfloat(windowWidth) / GLfloat(windowHeight), 0.1f, 1000.0f);
+    gluPerspective(45.0f, GLfloat(width) / GLfloat(height), 0.1f, 1000.0f);
 
     glMatrixMode(GL_MODELVIEW);
     glLoadIdentity();
@@ -118,6 +130,8 @@
 
     // Set correct perspective correction
     glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
+
+    return true;
 }
 
 
@@ -153,6 +167,9 @@
 
 void done()
 {
+    SDL_GL_DeleteContext(s_context);
+    SDL_DestroyWindow(s_window);
+    s_window = NULL;
     SDL_Quit();
 }
 
@@ -163,25 +180,21 @@
 
     glGetIntegerv(GL_MAX_ELEMENTS_INDICES, &maxIndices);
 
-
     glVertexPointer(3, GL_FLOAT, 24, &mesh.vertices[0]);
     glNormalPointer(GL_FLOAT, 24, &mesh.vertices[3]);
 
-
     for (size_t n = 0; n < mesh.faces.size() / 3; n += maxIndices)
     {
         const int count = std::min(maxIndices, int(mesh.faces.size() / 3 - n));
-
-        glDrawElements(GL_TRIANGLES, count * 3, GL_UNSIGNED_INT, &dragonMesh.faces[n * 3]);
+        glDrawElements(GL_TRIANGLES, count * 3, GL_UNSIGNED_INT, &mesh.faces[n * 3]);
     }
 }
 
 
-bool paintGL()
+void paintGL(Mesh &mesh)
 {
     glClear(GL_DEPTH_BUFFER_BIT);
 
-
     glMatrixMode(GL_PROJECTION);
     glPushMatrix();
     glLoadIdentity();
@@ -217,89 +230,39 @@
     glMatrixMode(GL_MODELVIEW);
     glPopMatrix();
 
+    glEnable(GL_DEPTH_TEST);
 
-    glEnable(GL_DEPTH_TEST);
     glEnable(GL_LIGHTING);
-
-
     // Set the color of the model
     glColor3ub(0x90, 0x80, 0x90);
 
-    // Draw the model using vertex arrays
-    drawModelVA(dragonMesh);
-
-    // Draw the current frame
-    SDL_GL_SwapBuffers();
 
 
 
-    static int steps = 0;
-
-    // Rotate for 2 degrees
-    glRotatef(2.0f, 0, 1, 0);
-
-    // Return true if a full rotation was done
-    return (steps++ == 180) ? (steps = 0, true) : false;
+    // Draw the model using vertex arrays
+    drawModelVA(mesh);
 }
 
 
-void runEventLoop()
+void loadMesh(const std::string& filename, Mesh& mesh, size_t nvertices, size_t nfaces)
 {
-    static std::clock_t startTime = std::clock();
-
-    while (true)
-    {
-        SDL_Event event;
-
-        if (SDL_PollEvent(&event))
-        {
-            if (event.type == SDL_QUIT)
-                break;
-        }
-        else
-        {
-            // Render the next frame and test if a full turn was completed
-            if (paintGL())
-            {
-                // Get the time it took to render a full turn
-                double time = double(std::clock() - startTime) / CLOCKS_PER_SEC;
-
-                // Print the current frames per second
-                std::printf("%.1lf seconds for 180 frames = %.1lf FPS\n", time, 180 / time);
-
-                // Restart the timer
-                startTime = std::clock();
-            }
-        }
-    }
-}
-
-
-void loadMesh(const std::string& fileName, Mesh& mesh)
-{
-    std::ifstream in(fileName.c_str(), std::ios::binary);
-
+    std::ifstream in(filename.c_str(), std::ios::binary);
 
     if (!in.is_open())
     {
         std::stringstream ss;
-
-        ss << "Unable to open file: " << fileName << '\n';
-
+        ss << "Unable to open file: " << filename << '\n';
         throw std::runtime_error(ss.str());
-
     }
 
-
-    mesh.vertices.resize(100139 * 6);
-    in.read(reinterpret_cast<char*>(&mesh.vertices[0]), 100139 * 6 * 4);
+    mesh.vertices.resize(nvertices * 6);
+    in.read(reinterpret_cast<char*>(&mesh.vertices[0]), nvertices * 6 * 4);
 
+    mesh.faces.resize(nfaces * 3);
 
-    mesh.faces.resize(200198 * 3);
-    for (unsigned i = 0; i < 200198; i++)
+    for (size_t i = 0; i < nfaces; i++)
     {
         in.seekg(1, std::ios::cur);
-
         in.read(reinterpret_cast<char*>(&mesh.faces[i * 3]), 3 * 4);
     }
 }
@@ -309,18 +272,72 @@
 {
     try
     {
-        loadMesh("dragon.mesh", dragonMesh);
+        struct Mesh dragonMesh;
+        loadMesh("dragon.mesh", dragonMesh, 100139, 200198);
 
-        init(640, 480, "glxdragon");
+        //if (!init(640, 480, "glxdragon"))
+        if (!init(1280, 960, "glxdragon"))
+            throw std::runtime_error("Fatal error.");
 
         initScene();
 
-        runEventLoop();
+        bool exitFlag = false;
+        int steps = 0;
+        std::clock_t startTime = std::clock();
+
+        while (!exitFlag)
+        {
+            SDL_Event event;
+
+            // 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_ESCAPE:
+                        case SDLK_q:
+                            exitFlag = true;
+                            break;
+                    }
+            }
+
+
+            // Render the next frame
+            paintGL(dragonMesh);
+
+            // Draw the current frame
+            SDL_GL_SwapWindow(s_window);
+
+            // Rotate for 2 degrees
+            glRotatef(2.0f, 0, 1, 0);
+
+            // Return true if a full rotation was done
+            if (steps++ == SET_FRAMES)
+            {
+                // Reset steps
+                steps = 0;
+
+                // Get the time it took to render a full turn
+                double time = (double(std::clock() - startTime) * 1000.0f) / CLOCKS_PER_SEC;
+
+                // Print the current frames per second
+                std::printf("%.1lf ms for %d frames = %.1lf FPS\n",
+                    time, SET_FRAMES, (SET_FRAMES * 1000.0f) / time);
+
+                // Restart the timer
+                startTime = std::clock();
+            }
+        }
     }
     catch(std::runtime_error & e)
     {
         std::cerr << e.what();
     }
-
     done();
 }