Mercurial > hg > forks > gldragon
comparison glxdragon.cpp @ 0:3d74a9dd96e4
Initial import of Thomas Trummer's original code.
author | Thomas Trummer |
---|---|
date | Sun, 27 Oct 2019 15:57:55 +0200 |
parents | |
children | b45d8958e5a6 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:3d74a9dd96e4 |
---|---|
1 | |
2 // Copyright (c) 2009, Thomas Trummer | |
3 // All rights reserved. | |
4 // | |
5 // Redistribution and use in source and binary forms, with or without | |
6 // modification, are permitted provided that the following conditions are met: | |
7 // * Redistributions of source code must retain the above copyright | |
8 // notice, this list of conditions and the following disclaimer. | |
9 // * Redistributions in binary form must reproduce the above copyright | |
10 // notice, this list of conditions and the following disclaimer in the | |
11 // documentation and/or other materials provided with the distribution. | |
12 // * Neither the name of the <organization> nor the | |
13 // names of its contributors may be used to endorse or promote products | |
14 // derived from this software without specific prior written permission. | |
15 // | |
16 // THIS SOFTWARE IS PROVIDED BY Thomas Trummer ''AS IS'' AND ANY | |
17 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
19 // DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY | |
20 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
21 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
22 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
23 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
24 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
25 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
26 | |
27 | |
28 #include <SDL.h> | |
29 #include <SDL_opengl.h> | |
30 | |
31 #include <iostream> | |
32 #include <sstream> | |
33 #include <fstream> | |
34 #include <stdexcept> | |
35 #include <string> | |
36 #include <vector> | |
37 #include <algorithm> | |
38 #include <cstdio> | |
39 #include <ctime> | |
40 | |
41 | |
42 struct Mesh | |
43 { | |
44 std::vector<float> vertices; | |
45 std::vector<unsigned> faces; | |
46 } | |
47 dragonMesh; | |
48 | |
49 | |
50 void init(const int windowWidth, const int windowHeight, const std::string& windowTitle) | |
51 { | |
52 std::stringstream ss; | |
53 | |
54 | |
55 if (SDL_Init(SDL_INIT_VIDEO) != 0) | |
56 { | |
57 ss << "Unable to initialize SDL: " << SDL_GetError() << '\n'; | |
58 | |
59 throw std::runtime_error(ss.str()); | |
60 } | |
61 | |
62 | |
63 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); | |
64 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); | |
65 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); | |
66 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); | |
67 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); | |
68 | |
69 | |
70 SDL_WM_SetCaption(windowTitle.c_str(), 0); | |
71 | |
72 | |
73 if ((SDL_SetVideoMode(windowWidth, windowHeight, 0, SDL_OPENGL)) == NULL) | |
74 { | |
75 ss << "Couldn't set GL mode: " << SDL_GetError() << '\n'; | |
76 | |
77 throw std::runtime_error(ss.str()); | |
78 } | |
79 | |
80 | |
81 std::cout << "GL_VENDOR : " << glGetString(GL_VENDOR) << std::endl; | |
82 std::cout << "GL_RENDERER : " << glGetString(GL_RENDERER) << std::endl; | |
83 std::cout << "GL_VERSION : " << glGetString(GL_VERSION) << std::endl; | |
84 | |
85 std::cout << std::endl; | |
86 | |
87 | |
88 // Setup the window and view port | |
89 glViewport(0, 0, windowWidth, windowHeight); | |
90 | |
91 glMatrixMode(GL_PROJECTION); | |
92 glLoadIdentity(); | |
93 | |
94 gluPerspective(45.0f, GLfloat(windowWidth) / GLfloat(windowHeight), 0.1f, 1000.0f); | |
95 | |
96 glMatrixMode(GL_MODELVIEW); | |
97 glLoadIdentity(); | |
98 | |
99 | |
100 // Enable back face culling | |
101 glEnable(GL_CULL_FACE); | |
102 | |
103 // Enable smooth shading | |
104 glShadeModel(GL_SMOOTH); | |
105 | |
106 // Enable the depth buffer | |
107 glEnable(GL_DEPTH_TEST); | |
108 | |
109 // Setup depth buffer | |
110 glClearDepth(1.0f); | |
111 | |
112 // Set the depth buffer function | |
113 glDepthFunc(GL_LEQUAL); | |
114 | |
115 // Enable vertex and and normal arrays | |
116 glEnableClientState(GL_VERTEX_ARRAY); | |
117 glEnableClientState(GL_NORMAL_ARRAY); | |
118 | |
119 // Set correct perspective correction | |
120 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); | |
121 } | |
122 | |
123 | |
124 void initScene() | |
125 { | |
126 glEnable(GL_COLOR_MATERIAL); | |
127 | |
128 glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); | |
129 glMateriali(GL_FRONT, GL_SHININESS, 96); | |
130 | |
131 float specReflection[] = { 0.8f, 0.8f, 0.8f, 1.0f }; | |
132 glMaterialfv(GL_FRONT, GL_SPECULAR, specReflection); | |
133 | |
134 | |
135 glEnable(GL_LIGHT0); | |
136 | |
137 // Define the light components and position | |
138 GLfloat ambient [] = { 0.2f, 0.2f, 0.2f, 1.0f }; | |
139 GLfloat diffuse [] = { 0.8f, 0.8f, 0.8f, 1.0f }; | |
140 GLfloat specular[] = { 0.5f, 0.5f, 0.5f, 1.0f }; | |
141 GLfloat position[] = { 10.0f, 10.0f, 0.0f, 0.0f }; | |
142 | |
143 // Define the light components and position | |
144 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); | |
145 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); | |
146 glLightfv(GL_LIGHT0, GL_SPECULAR, specular); | |
147 glLightfv(GL_LIGHT0, GL_POSITION, position); | |
148 | |
149 // Define the camera | |
150 gluLookAt(0, 0.12, 0.24, 0, 0.12, 0, 0, 1, 0); | |
151 } | |
152 | |
153 | |
154 void done() | |
155 { | |
156 SDL_Quit(); | |
157 } | |
158 | |
159 | |
160 void drawModelVA(const Mesh& mesh) | |
161 { | |
162 int maxIndices; | |
163 | |
164 glGetIntegerv(GL_MAX_ELEMENTS_INDICES, &maxIndices); | |
165 | |
166 | |
167 glVertexPointer(3, GL_FLOAT, 24, &mesh.vertices[0]); | |
168 glNormalPointer( GL_FLOAT, 24, &mesh.vertices[3]); | |
169 | |
170 | |
171 for(size_t n = 0; n < mesh.faces.size() / 3; n += maxIndices) | |
172 { | |
173 const int count = std::min(maxIndices, int(mesh.faces.size() / 3 - n)); | |
174 | |
175 glDrawElements(GL_TRIANGLES, count * 3, GL_UNSIGNED_INT, &dragonMesh.faces[n * 3]); | |
176 } | |
177 } | |
178 | |
179 | |
180 bool paintGL() | |
181 { | |
182 glClear(GL_DEPTH_BUFFER_BIT); | |
183 | |
184 | |
185 glMatrixMode(GL_PROJECTION); | |
186 glPushMatrix(); | |
187 glLoadIdentity(); | |
188 | |
189 glOrtho(0.0, 1.0, 0.0, 1.0, -1, 1); | |
190 | |
191 glMatrixMode(GL_MODELVIEW); | |
192 glPushMatrix(); | |
193 glLoadIdentity(); | |
194 | |
195 | |
196 glDisable(GL_DEPTH_TEST); | |
197 glDisable(GL_LIGHTING); | |
198 | |
199 // Draw the background gradient | |
200 glBegin(GL_QUADS); | |
201 { | |
202 glColor3ub(0x3B, 0x3B, 0x75); | |
203 glVertex2f(0.0f, 0.0f); | |
204 glVertex2f(1.0f, 0.0f); | |
205 | |
206 glColor3ub(0x00, 0x00, 0x00); | |
207 glVertex2f(1.0f, 1.0f); | |
208 glVertex2f(0.0f, 1.0f); | |
209 } | |
210 glEnd(); | |
211 | |
212 | |
213 // Restore the 3D projection | |
214 glMatrixMode(GL_PROJECTION); | |
215 glPopMatrix(); | |
216 | |
217 glMatrixMode(GL_MODELVIEW); | |
218 glPopMatrix(); | |
219 | |
220 | |
221 glEnable(GL_DEPTH_TEST); | |
222 glEnable(GL_LIGHTING); | |
223 | |
224 | |
225 // Set the color of the model | |
226 glColor3ub(0x90, 0x80, 0x90); | |
227 | |
228 // Draw the model using vertex arrays | |
229 drawModelVA(dragonMesh); | |
230 | |
231 // Draw the current frame | |
232 SDL_GL_SwapBuffers(); | |
233 | |
234 | |
235 | |
236 static int steps = 0; | |
237 | |
238 // Rotate for 2 degrees | |
239 glRotatef(2.0f, 0, 1, 0); | |
240 | |
241 // Return true if a full rotation was done | |
242 return (steps++ == 180) ? (steps = 0, true) : false; | |
243 } | |
244 | |
245 | |
246 void runEventLoop() | |
247 { | |
248 static std::clock_t startTime = std::clock(); | |
249 | |
250 while (true) | |
251 { | |
252 SDL_Event event; | |
253 | |
254 if (SDL_PollEvent(&event)) | |
255 { | |
256 if (event.type == SDL_QUIT) | |
257 break; | |
258 } | |
259 else | |
260 { | |
261 // Render the next frame and test if a full turn was completed | |
262 if (paintGL()) | |
263 { | |
264 // Get the time it took to render a full turn | |
265 double time = double(std::clock() - startTime) / CLOCKS_PER_SEC; | |
266 | |
267 // Print the current frames per second | |
268 std::printf("%.1lf seconds for 180 frames = %.1lf FPS\n", time, 180 / time); | |
269 | |
270 // Restart the timer | |
271 startTime = std::clock(); | |
272 } | |
273 } | |
274 } | |
275 } | |
276 | |
277 | |
278 void loadMesh(const std::string& fileName, Mesh& mesh) | |
279 { | |
280 std::ifstream in(fileName.c_str(), std::ios::binary); | |
281 | |
282 | |
283 if (!in.is_open()) | |
284 { | |
285 std::stringstream ss; | |
286 | |
287 ss << "Unable to open file: " << fileName << '\n'; | |
288 | |
289 throw std::runtime_error(ss.str()); | |
290 | |
291 } | |
292 | |
293 | |
294 mesh.vertices.resize(100139 * 6); | |
295 | |
296 in.read(reinterpret_cast<char*>(&mesh.vertices[0]), 100139 * 6 * 4); | |
297 | |
298 | |
299 mesh.faces.resize(200198 * 3); | |
300 | |
301 | |
302 for(unsigned i = 0; i < 200198; i++) | |
303 { | |
304 in.seekg(1, std::ios::cur); | |
305 | |
306 in.read(reinterpret_cast<char*>(&mesh.faces[i*3]), 3 * 4); | |
307 } | |
308 } | |
309 | |
310 | |
311 int main() | |
312 { | |
313 try | |
314 { | |
315 loadMesh("dragon.mesh", dragonMesh); | |
316 | |
317 init(640, 480, "glxdragon"); | |
318 | |
319 initScene(); | |
320 | |
321 runEventLoop(); | |
322 } | |
323 catch(std::runtime_error& e) | |
324 { | |
325 std::cerr << e.what(); | |
326 } | |
327 | |
328 done(); | |
329 } |