Mercurial > hg > forks > gldragon
view glxdragon.cpp @ 1:4727156927ea
One must use g++ for C++ code, otherwise libstdc++ won't get linked in.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Sun, 27 Oct 2019 17:19:47 +0200 |
parents | 3d74a9dd96e4 |
children | b45d8958e5a6 |
line wrap: on
line source
// 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 <organization> 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 <copyright holder> 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 <SDL.h> #include <SDL_opengl.h> #include <iostream> #include <sstream> #include <fstream> #include <stdexcept> #include <string> #include <vector> #include <algorithm> #include <cstdio> #include <ctime> struct Mesh { std::vector<float> vertices; std::vector<unsigned> 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<char*>(&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<char*>(&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(); }