# HG changeset patch # User Thomas Trummer # Date 1572184675 -7200 # Node ID 3d74a9dd96e4bb12bd2cfb76a5d2b1bb3a88f287 Initial import of Thomas Trummer's original code. diff -r 000000000000 -r 3d74a9dd96e4 Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Makefile Sun Oct 27 15:57:55 2019 +0200 @@ -0,0 +1,11 @@ + +CC = gcc +CFLAGS = -O2 -Wall -I/usr/include/SDL +LDFLAGS = -lSDL -lGL -lGLU + +glxdragon: glxdragon.cpp + $(CC) $(CFLAGS) -o glxdragon glxdragon.cpp $(LDFLAGS) + +clean: + rm glxdragon + diff -r 000000000000 -r 3d74a9dd96e4 dragon.mesh Binary file dragon.mesh has changed diff -r 000000000000 -r 3d74a9dd96e4 glxdragon.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/glxdragon.cpp Sun Oct 27 15:57:55 2019 +0200 @@ -0,0 +1,329 @@ + +// Copyright (c) 2009, Thomas Trummer +// All rights reserved. +// +// 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 +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the nor the +// names of its contributors may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY Thomas Trummer ''AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +struct Mesh +{ + std::vector vertices; + std::vector faces; +} +dragonMesh; + + +void init(const int windowWidth, const int windowHeight, const std::string& windowTitle) +{ + std::stringstream ss; + + + if (SDL_Init(SDL_INIT_VIDEO) != 0) + { + ss << "Unable to initialize SDL: " << SDL_GetError() << '\n'; + + throw std::runtime_error(ss.str()); + } + + + 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_SetVideoMode(windowWidth, windowHeight, 0, SDL_OPENGL)) == NULL) + { + ss << "Couldn't set GL mode: " << SDL_GetError() << '\n'; + + throw std::runtime_error(ss.str()); + } + + + 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; + + + // Setup the window and view port + glViewport(0, 0, windowWidth, windowHeight); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + gluPerspective(45.0f, GLfloat(windowWidth) / GLfloat(windowHeight), 0.1f, 1000.0f); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + + // Enable back face culling + glEnable(GL_CULL_FACE); + + // Enable smooth shading + glShadeModel(GL_SMOOTH); + + // Enable the depth buffer + glEnable(GL_DEPTH_TEST); + + // Setup depth buffer + glClearDepth(1.0f); + + // Set the depth buffer function + glDepthFunc(GL_LEQUAL); + + // Enable vertex and and normal arrays + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); + + // Set correct perspective correction + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); +} + + +void initScene() +{ + glEnable(GL_COLOR_MATERIAL); + + glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); + glMateriali(GL_FRONT, GL_SHININESS, 96); + + float specReflection[] = { 0.8f, 0.8f, 0.8f, 1.0f }; + glMaterialfv(GL_FRONT, GL_SPECULAR, specReflection); + + + glEnable(GL_LIGHT0); + + // Define the light components and position + GLfloat ambient [] = { 0.2f, 0.2f, 0.2f, 1.0f }; + GLfloat diffuse [] = { 0.8f, 0.8f, 0.8f, 1.0f }; + GLfloat specular[] = { 0.5f, 0.5f, 0.5f, 1.0f }; + GLfloat position[] = { 10.0f, 10.0f, 0.0f, 0.0f }; + + // Define the light components and position + glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); + glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); + glLightfv(GL_LIGHT0, GL_SPECULAR, specular); + glLightfv(GL_LIGHT0, GL_POSITION, position); + + // Define the camera + gluLookAt(0, 0.12, 0.24, 0, 0.12, 0, 0, 1, 0); +} + + +void done() +{ + SDL_Quit(); +} + + +void drawModelVA(const Mesh& mesh) +{ + int maxIndices; + + 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]); + } +} + + +bool paintGL() +{ + glClear(GL_DEPTH_BUFFER_BIT); + + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glOrtho(0.0, 1.0, 0.0, 1.0, -1, 1); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + + + glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + + // Draw the background gradient + glBegin(GL_QUADS); + { + glColor3ub(0x3B, 0x3B, 0x75); + glVertex2f(0.0f, 0.0f); + glVertex2f(1.0f, 0.0f); + + glColor3ub(0x00, 0x00, 0x00); + glVertex2f(1.0f, 1.0f); + glVertex2f(0.0f, 1.0f); + } + glEnd(); + + + // Restore the 3D projection + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + + 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; +} + + +void runEventLoop() +{ + 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); + + + if (!in.is_open()) + { + std::stringstream ss; + + ss << "Unable to open file: " << fileName << '\n'; + + throw std::runtime_error(ss.str()); + + } + + + mesh.vertices.resize(100139 * 6); + + in.read(reinterpret_cast(&mesh.vertices[0]), 100139 * 6 * 4); + + + mesh.faces.resize(200198 * 3); + + + for(unsigned i = 0; i < 200198; i++) + { + in.seekg(1, std::ios::cur); + + in.read(reinterpret_cast(&mesh.faces[i*3]), 3 * 4); + } +} + + +int main() +{ + try + { + loadMesh("dragon.mesh", dragonMesh); + + init(640, 480, "glxdragon"); + + initScene(); + + runEventLoop(); + } + catch(std::runtime_error& e) + { + std::cerr << e.what(); + } + + done(); +}