/*
* Copyright (C) 2009 Tilman Sauerbeck (tilman at code-monkey de)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
/* Renders Archimedean Dynasty (aka Schleichfahrt) model files (*.MOD)
* in wireframe mode.
*
* Probably quite horrible. I suck at OpenGL.
*/
#include
#include
#include
#include
#include
#include
#include
typedef struct {
uint32_t id;
float x;
float y;
float z;
} ModelVertex;
static struct {
float x;
float y;
float z;
} camera;
static int window;
static ModelVertex model_vertices[255];
static int num_vertices;
static int
cmp_model_vertex (const void *a, const void *b)
{
const ModelVertex *aa = a;
const ModelVertex *bb = b;
if (aa->id < bb->id)
return -1;
else if (aa->id > bb->id)
return +1;
else
return 0;
}
static void
read_file (const char *filename)
{
FILE *f;
int i;
f = fopen (filename, "rb");
if (!f) {
fprintf (stderr, "cannot open %s\n", filename);
exit (EXIT_FAILURE);
}
fseek (f, 10, SEEK_SET);
fread (&num_vertices, 4, 1, f);
fseek (f, 18, SEEK_SET);
for (i = 0; i < num_vertices; i++) {
ModelVertex *vertex = &model_vertices[i];
fread (&vertex->id, 4, 1, f);
fread (&vertex->x, 4, 1, f);
fread (&vertex->y, 4, 1, f);
fread (&vertex->z, 4, 1, f);
}
fclose (f);
#if 0
// sort vertices by id
qsort (model_vertices, num_vertices, sizeof (ModelVertex *),
cmp_model_vertex);
#endif
}
static void
reset_matrix (int width, int height)
{
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective (45.0f,
(GLfloat) width / (GLfloat) height,
0.1f, 100.0f);
glMatrixMode (GL_MODELVIEW);
}
static void
init_gl (int width, int height)
{
glClearColor (0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth (1.0);
glDepthFunc (GL_LESS);
glEnable (GL_DEPTH_TEST);
glShadeModel (GL_SMOOTH);
reset_matrix (width, height);
}
static void
draw_gl_scene (void)
{
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity ();
// Move Left 1.5 Units And Into The Screen 90.0
float into_the_screen = -90.0f;
//glTranslatef (-1.5f, 0.0f, into_the_screen);
//glTranslatef (0.0f, 0.0f, -120.0f);
glTranslatef (camera.x, camera.y, camera.z);
// Rotate the triangle on the X axis
//glRotatef (-45.0, 1.0f, 0.0f, 0.0f);
// Draw wireframe
glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
#if 0
glBegin (GL_POLYGON); {
int i;
for (i = 0; i < 122; i++) {
ModelVertex *vertex = &model_vertices[i];
glVertex3f (vertex->x, vertex->y, vertex->z);
}
} glEnd ();
#else
glBegin (GL_TRIANGLE_STRIP); {
int i;
for (i = 0; i < 122; i++) {
ModelVertex *vertex = &model_vertices[i];
if (i == 50)
glColor3f (1.0, 0.0, 0.0);
else
glColor3f (0.0, 0.0, 1.0);
glVertex3f (vertex->x, vertex->y, vertex->z);
}
} glEnd ();
#endif
glutSwapBuffers ();
}
static void
resize_gl_scene (int width, int height)
{
glViewport (0, 0, width, height);
reset_matrix (width, height);
}
static void
key_pressed (unsigned char key, int x, int y)
{
usleep (100);
switch (key) {
case 27:
glutDestroyWindow (window);
exit (0);
case 'h':
camera.x += 1.0f;
break;
case 'l':
camera.x -= 1.0f;
break;
case 'j':
camera.y += 1.0f;
break;
case 'k':
camera.y -= 1.0f;
break;
case 'a':
camera.z += 1.0f;
break;
case 'z':
camera.z -= 1.0f;
break;
default:
printf("%i\n", key);
break;
}
}
int
main (int argc, char **argv)
{
/* Read the MOD file. */
read_file (argv[1]);
camera.x = 0.0f;
camera.y = 0.0f;
camera.z = 0.0f;
glutInit (&argc, argv);
glutInitDisplayMode (GLUT_RGBA | GLUT_DOUBLE |
GLUT_ALPHA | GLUT_DEPTH);
glutInitWindowSize (640, 480);
window = glutCreateWindow ("foo");
glutDisplayFunc (draw_gl_scene);
glutIdleFunc (draw_gl_scene);
glutReshapeFunc (resize_gl_scene);
glutKeyboardFunc (key_pressed);
init_gl (640, 480);
glutMainLoop ();
return EXIT_SUCCESS;
}