changeset 0:3d74a9dd96e4

Initial import of Thomas Trummer's original code.
author Thomas Trummer
date Sun, 27 Oct 2019 15:57:55 +0200
parents
children 4727156927ea
files Makefile dragon.mesh glxdragon.cpp
diffstat 3 files changed, 340 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /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
+
Binary file dragon.mesh has changed
--- /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 <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();
+}