Illegal Instruction
Still Fresh
- Joined
- Aug 5, 2011
- Messages
- 2
Hi all,
I just figured out how to code up an .MD2 renderer, and, even with the inefficiencies I know are probably lurking just beneath the surface, it seems fast and easy to use, so I thought I'd post it here for other newbies to reuse/learn from/laugh at.
I got the file format information from http://icculus.org/~phaethon/q3a/formats/md2-schoenblum.html.
Here are the goods:
md2_model.h:
md2_model.c:
anorms.h
Edit: one caveat - the exists() function is an Allegroism - you'll either need to strip it out or replace it if you're not using Allegro.
I just figured out how to code up an .MD2 renderer, and, even with the inefficiencies I know are probably lurking just beneath the surface, it seems fast and easy to use, so I thought I'd post it here for other newbies to reuse/learn from/laugh at.
I got the file format information from http://icculus.org/~phaethon/q3a/formats/md2-schoenblum.html.
Here are the goods:
md2_model.h:
Code:
/** Pandora-friendly Quake II model drawing code.
*
* (after Shawn Hargreaves)
*
* This is gift-ware. It was created by someone with too much free time
* who has learned a lot due to the generosity of others,
* and is given to you freely as a gift. You may use, modify,
* redistribute, and generally hack it about in any way you like,
* and you do not have to give me anything in return.
*
* However, if you like this product you are encouraged to thank me by
* making a return gift to the Pandora community. This could be by porting
* a package, providing a useful bug report, making an improvement to an
* existing library, or perhaps just releasing the sources of your program
* so that other people can learn from them. If you redistribute parts of
* this code or make a game using it, it would be nice if you mentioned
* where you got it somewhere in the credits, but you are not required to
* do this.
*
* We trust you not to abuse our generosity.
*/
#ifndef __MD2_MODEL_H
#define __MD2_MODEL_H
#include <allegro.h>
#ifdef __OPENPANDORA__
#include <GLES/gl.h>
#include <GLES/egl.h>
#else
#include <alleggl.h>
#endif
typedef struct
{
unsigned int ident;
unsigned int version;
unsigned int skin_width; /* ignored */
unsigned int skin_height; /* ignored */
unsigned int frame_size;
unsigned int num_skins; /* ignored */
unsigned int num_vertices;
unsigned int num_texture_coords;
unsigned int num_triangles;
unsigned int num_gl_commands;
unsigned int num_frames;
unsigned int offset_skins; /* ignored */
unsigned int offset_texture_coords;
unsigned int offset_triangles;
unsigned int offset_frames;
unsigned int offset_gl_commands;
unsigned int offset_end;
} MD2_HEADER_STRUCT;
/************************************************************/
typedef struct
{
GLfloat u;
GLfloat v;
}
MD2_TEXCOORD;
/************************************************************/
typedef struct
{
unsigned char unscaled_x;
unsigned char unscaled_y;
unsigned char unscaled_z;
unsigned char normal_list_index; /* using the id surface normals */
} MD2_VERTEX_STRUCT;
/*****************************************************************/
typedef struct
{
float x;
float y;
float z;
} DRAWABLE_VERT;
typedef struct
{
float u;
float v;
} DRAWABLE_UV;
/*****************************************************************/
typedef struct
{
float tex_coord_x;
float tex_coord_y;
unsigned int vertex_list_index;
} MD2_TRISTRIP_TRIFAN_ELEMENT;
/*****************************************************************/
typedef struct
{
short vertex_indices[3];
short texture_indices[3];
} MD2_TRIANGLE;
/*****************************************************************/
typedef struct
{
float scale_x;
float scale_y;
float scale_z;
float translate_x;
float translate_y;
float translate_z;
MD2_VERTEX_STRUCT * vertices;
} MD2_ANIM_FRAME_STRUCT;
/*****************************************************************/
typedef struct
{
MD2_ANIM_FRAME_STRUCT* anim_frames;
MD2_TRIANGLE* triangles;
MD2_TEXCOORD* tex_coords;
DRAWABLE_VERT* vert_array;
DRAWABLE_VERT* norm_array;
DRAWABLE_UV* uv_array;
unsigned int num_frames;
unsigned int num_triangles;
unsigned int num_texcoords;
unsigned int num_drawable;
unsigned int num_vertices;
} MD2_MODEL;
/*****************************************************************/
MD2_MODEL * MD2_load(const char *filename);
void MD2_draw(const MD2_MODEL * model, GLuint tex,
GLfloat x, GLfloat y, GLfloat z,
GLfloat y_rot,
int curr_frame, int next_frame, float tween);
void MD2_unload(MD2_MODEL * model);
#endif
md2_model.c:
Code:
#include <stdio.h>
#include <allegro.h>
#include "md2_model.h"
#include "anorms.h"
/******************************************************************************/
/*!
* Load a Quake II model from disk and fill out an MD2_MODEL data structure
* with it.
*
* Returns null if it couldn't find or open the specified file.
*/
MD2_MODEL * MD2_load(const char *filename)
{
MD2_HEADER_STRUCT header;
FILE *fin;
int index;
int element_index;
int dest;
short tmp;
MD2_MODEL *ret;
if(!exists(filename))
{
return NULL;
}
fin = fopen(filename,"rb");
fread(&header,sizeof(MD2_HEADER_STRUCT),1,fin);
ret = (MD2_MODEL*)malloc(sizeof(MD2_MODEL));
if(ret == NULL)
{
fclose(fin);
return NULL;
}
// get how much geometry we need to store
ret->num_frames = header.num_frames;
ret->num_triangles = header.num_triangles;
ret->num_vertices = header.num_vertices;
ret->num_texcoords = header.num_texture_coords;
// allocate enough space to hold the geometry
ret->anim_frames = (MD2_ANIM_FRAME_STRUCT *)malloc(sizeof(MD2_ANIM_FRAME_STRUCT) * ret->num_frames);
for(index = 0; index < header.num_frames; index++)
{
ret->anim_frames[index].vertices = (MD2_VERTEX_STRUCT *)malloc(sizeof(MD2_VERTEX_STRUCT) * ret->num_vertices);
}
ret->triangles = (MD2_TRIANGLE *)malloc(sizeof(MD2_TRIANGLE) * ret->num_triangles);
ret->vert_array = (DRAWABLE_VERT *)malloc(sizeof(DRAWABLE_VERT) * ret->num_triangles * 3);
ret->norm_array = (DRAWABLE_VERT *)malloc(sizeof(DRAWABLE_VERT) * ret->num_triangles * 3);
ret->uv_array = (DRAWABLE_UV *)malloc(sizeof(DRAWABLE_UV) * ret->num_triangles * 3);
fseek(fin,header.offset_texture_coords,SEEK_SET);
ret->tex_coords = (MD2_TEXCOORD*)malloc(sizeof(MD2_TEXCOORD) * ret->num_texcoords);
for(index = 0; index < header.num_texture_coords; index++)
{
fread(&tmp,sizeof(short),1,fin);
ret->tex_coords[index].u = tmp / (float)header.skin_width;
fread(&tmp,sizeof(short),1,fin);
ret->tex_coords[index].v = tmp / (float)header.skin_height;
}
// read vertex and uv coord indices.
fseek(fin,header.offset_triangles,SEEK_SET);
for(element_index = 0; element_index < header.num_triangles; element_index++)
{
fread(&ret->triangles[element_index].vertex_indices[0],sizeof(short),1,fin);
fread(&ret->triangles[element_index].vertex_indices[1],sizeof(short),1,fin);
fread(&ret->triangles[element_index].vertex_indices[2],sizeof(short),1,fin);
fread(&ret->triangles[element_index].texture_indices[0],sizeof(short),1,fin);
fread(&ret->triangles[element_index].texture_indices[1],sizeof(short),1,fin);
fread(&ret->triangles[element_index].texture_indices[2],sizeof(short),1,fin);
}
// read actual frame details and encoded verts
fseek(fin,header.offset_frames,SEEK_SET);
// it isn't clear why, but the coordinates are stored x, z, y rather
// than x, y, z...? endianness confusion on my part, perhaps
for(index = 0; index < ret->num_frames; index++)
{
element_index = 0;
fread(&ret->anim_frames[index].scale_x,sizeof(float),1,fin);
fread(&ret->anim_frames[index].scale_y,sizeof(float),1,fin);
fread(&ret->anim_frames[index].scale_z,sizeof(float),1,fin);
fread(&ret->anim_frames[index].translate_x,sizeof(float),1,fin);
fread(&ret->anim_frames[index].translate_z,sizeof(float),1,fin);
fread(&ret->anim_frames[index].translate_y,sizeof(float),1,fin);
fseek(fin, 16, SEEK_CUR);
do
{
fread(&ret->anim_frames[index].vertices[element_index].unscaled_x, sizeof(char), 1, fin);
fread(&ret->anim_frames[index].vertices[element_index].unscaled_z, sizeof(char), 1, fin);
fread(&ret->anim_frames[index].vertices[element_index].unscaled_y, sizeof(char), 1, fin);
fread(&ret->anim_frames[index].vertices[element_index].normal_list_index, sizeof(char), 1, fin);
element_index++;
}
while(element_index < header.num_vertices);
}
fclose(fin);
return ret;
}
/******************************************************************************/
/*!
* Draw the specified model with the specified texture at the specified
* coordinates, with the specified animation frames and tweening.
*
* TODO:
* - make this use tri-strips and tri-fans.
* - profile on Pandora, see how many models we can draw before it bogs down.
* - optionally move texture binding out of here; that way, we can sort
* models by texture and draw them all at once without paying for
* extra state changes.
*/
void MD2_draw(const MD2_MODEL * model, GLuint tex, GLfloat x, GLfloat y, GLfloat z, GLfloat y_rot, int curr_frame, int next_frame, float tween)
{
float scaled_x0, scaled_y0, scaled_z0;
float scaled_x1, scaled_y1, scaled_z1;
float scaled_x, scaled_y, scaled_z;
int tri_index;
float one_minus_tween = 1.0f - tween;
glPushMatrix();
glTranslatef(x,y,z);
glRotatef(y_rot,0,1,0);
for(tri_index = 0; tri_index < model->num_triangles; tri_index++)
{
//========= first point ==========
//--- vertex ----
scaled_x = (( (float)model->anim_frames[curr_frame].vertices[model->triangles[tri_index].vertex_indices[0]].unscaled_x *
model->anim_frames[curr_frame].scale_x + model->anim_frames[curr_frame].translate_x) * one_minus_tween) +
(( (float)model->anim_frames[next_frame].vertices[model->triangles[tri_index].vertex_indices[0]].unscaled_x *
model->anim_frames[next_frame].scale_x + model->anim_frames[next_frame].translate_x) * tween);
scaled_y = (( (float)model->anim_frames[curr_frame].vertices[model->triangles[tri_index].vertex_indices[0]].unscaled_y *
model->anim_frames[curr_frame].scale_y + model->anim_frames[curr_frame].translate_y) * one_minus_tween) +
(( (float)model->anim_frames[next_frame].vertices[model->triangles[tri_index].vertex_indices[0]].unscaled_y *
model->anim_frames[next_frame].scale_y + model->anim_frames[next_frame].translate_y) * tween);
scaled_z = (( (float)model->anim_frames[curr_frame].vertices[model->triangles[tri_index].vertex_indices[0]].unscaled_z *
model->anim_frames[curr_frame].scale_z + model->anim_frames[curr_frame].translate_z) * one_minus_tween) +
(( (float)model->anim_frames[next_frame].vertices[model->triangles[tri_index].vertex_indices[0]].unscaled_z *
model->anim_frames[next_frame].scale_z + model->anim_frames[next_frame].translate_z) * tween);
model->vert_array[tri_index * 3 + 0].x = scaled_x;
model->vert_array[tri_index * 3 + 0].y = scaled_y;
model->vert_array[tri_index * 3 + 0].z = scaled_z;
//--- normal ----
scaled_x = (normal_list[ model->anim_frames[curr_frame].vertices[model->triangles[tri_index].vertex_indices[0]].normal_list_index][ 0] * one_minus_tween) +
(normal_list[ model->anim_frames[next_frame].vertices[model->triangles[tri_index].vertex_indices[0]].normal_list_index][ 0] * tween);
scaled_y = (normal_list[ model->anim_frames[curr_frame].vertices[model->triangles[tri_index].vertex_indices[0]].normal_list_index][ 1] * one_minus_tween) +
(normal_list[ model->anim_frames[next_frame].vertices[model->triangles[tri_index].vertex_indices[0]].normal_list_index][ 1] * tween);
scaled_z = (normal_list[ model->anim_frames[curr_frame].vertices[model->triangles[tri_index].vertex_indices[0]].normal_list_index][ 2] * one_minus_tween) +
(normal_list[ model->anim_frames[next_frame].vertices[model->triangles[tri_index].vertex_indices[0]].normal_list_index][ 2] * tween);
model->norm_array[tri_index * 3 + 0].x = scaled_x;
model->norm_array[tri_index * 3 + 0].z = scaled_y;
model->norm_array[tri_index * 3 + 0].y = scaled_z;
//--- tex coord ----
model->uv_array[tri_index * 3 + 0].u = model->tex_coords[model->triangles[tri_index].texture_indices[0]].u;
model->uv_array[tri_index * 3 + 0].v = model->tex_coords[model->triangles[tri_index].texture_indices[0]].v;
//========= second point ==========
//--- vertex ----
scaled_x = (( (float)model->anim_frames[curr_frame].vertices[model->triangles[tri_index].vertex_indices[1]].unscaled_x *
model->anim_frames[curr_frame].scale_x + model->anim_frames[curr_frame].translate_x) * one_minus_tween) +
(( (float)model->anim_frames[next_frame].vertices[model->triangles[tri_index].vertex_indices[1]].unscaled_x *
model->anim_frames[next_frame].scale_x + model->anim_frames[next_frame].translate_x) * tween);
scaled_y = (( (float)model->anim_frames[curr_frame].vertices[model->triangles[tri_index].vertex_indices[1]].unscaled_y *
model->anim_frames[curr_frame].scale_y + model->anim_frames[curr_frame].translate_y) * one_minus_tween) +
(( (float)model->anim_frames[next_frame].vertices[model->triangles[tri_index].vertex_indices[1]].unscaled_y *
model->anim_frames[next_frame].scale_y + model->anim_frames[next_frame].translate_y) * tween);
scaled_z = (( (float)model->anim_frames[curr_frame].vertices[model->triangles[tri_index].vertex_indices[1]].unscaled_z *
model->anim_frames[curr_frame].scale_z + model->anim_frames[curr_frame].translate_z) * one_minus_tween) +
(( (float)model->anim_frames[next_frame].vertices[model->triangles[tri_index].vertex_indices[1]].unscaled_z *
model->anim_frames[next_frame].scale_z + model->anim_frames[next_frame].translate_z) * tween);
model->vert_array[tri_index * 3 + 1].x = scaled_x;
model->vert_array[tri_index * 3 + 1].y = scaled_y;
model->vert_array[tri_index * 3 + 1].z = scaled_z;
//--- normal ----
scaled_x = (normal_list[ model->anim_frames[curr_frame].vertices[model->triangles[tri_index].vertex_indices[1]].normal_list_index][ 0] * one_minus_tween) +
(normal_list[ model->anim_frames[next_frame].vertices[model->triangles[tri_index].vertex_indices[1]].normal_list_index][ 0] * tween);
scaled_y = (normal_list[ model->anim_frames[curr_frame].vertices[model->triangles[tri_index].vertex_indices[1]].normal_list_index][ 1] * one_minus_tween) +
(normal_list[ model->anim_frames[next_frame].vertices[model->triangles[tri_index].vertex_indices[1]].normal_list_index][ 1] * tween);
scaled_z = (normal_list[ model->anim_frames[curr_frame].vertices[model->triangles[tri_index].vertex_indices[1]].normal_list_index][ 2] * one_minus_tween) +
(normal_list[ model->anim_frames[next_frame].vertices[model->triangles[tri_index].vertex_indices[1]].normal_list_index][ 2] * tween);
model->norm_array[tri_index * 3 + 1].x = scaled_x;
model->norm_array[tri_index * 3 + 1].z = scaled_y;
model->norm_array[tri_index * 3 + 1].y = scaled_z;
//--- tex coord ----
model->uv_array[tri_index * 3 + 1].u = model->tex_coords[model->triangles[tri_index].texture_indices[1]].u;
model->uv_array[tri_index * 3 + 1].v = model->tex_coords[model->triangles[tri_index].texture_indices[1]].v;
//========= third point ==========
//--- vertex ----
scaled_x = (( (float)model->anim_frames[curr_frame].vertices[model->triangles[tri_index].vertex_indices[2]].unscaled_x *
model->anim_frames[curr_frame].scale_x + model->anim_frames[curr_frame].translate_x) * one_minus_tween) +
(( (float)model->anim_frames[next_frame].vertices[model->triangles[tri_index].vertex_indices[2]].unscaled_x *
model->anim_frames[next_frame].scale_x + model->anim_frames[next_frame].translate_x) * tween);
scaled_y = (( (float)model->anim_frames[curr_frame].vertices[model->triangles[tri_index].vertex_indices[2]].unscaled_y *
model->anim_frames[curr_frame].scale_y + model->anim_frames[curr_frame].translate_y) * one_minus_tween) +
(( (float)model->anim_frames[next_frame].vertices[model->triangles[tri_index].vertex_indices[2]].unscaled_y *
model->anim_frames[next_frame].scale_y + model->anim_frames[next_frame].translate_y) * tween);
scaled_z = (( (float)model->anim_frames[curr_frame].vertices[model->triangles[tri_index].vertex_indices[2]].unscaled_z *
model->anim_frames[curr_frame].scale_z + model->anim_frames[curr_frame].translate_z) * one_minus_tween) +
(( (float)model->anim_frames[next_frame].vertices[model->triangles[tri_index].vertex_indices[2]].unscaled_z *
model->anim_frames[next_frame].scale_z + model->anim_frames[next_frame].translate_z) * tween);
model->vert_array[tri_index * 3 + 2].x = scaled_x;
model->vert_array[tri_index * 3 + 2].y = scaled_y;
model->vert_array[tri_index * 3 + 2].z = scaled_z;
//--- normal ----
scaled_x = (normal_list[ model->anim_frames[curr_frame].vertices[model->triangles[tri_index].vertex_indices[2]].normal_list_index][ 0] * one_minus_tween) +
(normal_list[ model->anim_frames[next_frame].vertices[model->triangles[tri_index].vertex_indices[2]].normal_list_index][ 0] * tween);
scaled_y = (normal_list[ model->anim_frames[curr_frame].vertices[model->triangles[tri_index].vertex_indices[2]].normal_list_index][ 1] * one_minus_tween) +
(normal_list[ model->anim_frames[next_frame].vertices[model->triangles[tri_index].vertex_indices[2]].normal_list_index][ 1] * tween);
scaled_z = (normal_list[ model->anim_frames[curr_frame].vertices[model->triangles[tri_index].vertex_indices[2]].normal_list_index][ 2] * one_minus_tween) +
(normal_list[ model->anim_frames[next_frame].vertices[model->triangles[tri_index].vertex_indices[2]].normal_list_index][ 2] * tween);
model->norm_array[tri_index * 3 + 2].x = scaled_x;
model->norm_array[tri_index * 3 + 2].z = scaled_y;
model->norm_array[tri_index * 3 + 2].y = scaled_z;
//--- tex coord ----
model->uv_array[tri_index * 3 + 2].u = model->tex_coords[model->triangles[tri_index].texture_indices[2]].u;
model->uv_array[tri_index * 3 + 2].v = model->tex_coords[model->triangles[tri_index].texture_indices[2]].v;
}
glVertexPointer(3,GL_FLOAT,0,model->vert_array);
glTexCoordPointer(2,GL_FLOAT,0,model->uv_array);
glNormalPointer(GL_FLOAT,0,model->norm_array);
glBindTexture(GL_TEXTURE_2D,tex);
glDrawArrays(GL_TRIANGLES,0,model->num_triangles*3);
glPopMatrix();
}
/******************************************************************************/
/*!
* Discard the specified model and free up memory.
*/
void MD2_unload(MD2_MODEL *ret)
{
int index;
if(ret == NULL)
{
// nothing to do here
return;
}
free(ret->tex_coords);
free(ret->vert_array);
free(ret->norm_array);
free(ret->uv_array);
free(ret->triangles);
for(index = 0; index < ret->num_frames; index++)
{
free(ret->anim_frames[index].vertices);
}
free(ret->anim_frames);
free(ret);
}
anorms.h
Code:
#ifndef __ANORMS_H
#define __ANORMS_H
/*!
* The id normal list, use these for building array that gets
* passed to glNormalPointer.
*/
float normal_list[][3] =
{
{ -0.525731f, 0.000000f, 0.850651f },
{ -0.442863f, 0.238856f, 0.864188f },
{ -0.295242f, 0.000000f, 0.955423f },
{ -0.309017f, 0.500000f, 0.809017f },
{ -0.162460f, 0.262866f, 0.951056f },
{ 0.000000f, 0.000000f, 1.000000f },
{ 0.000000f, 0.850651f, 0.525731f },
{ -0.147621f, 0.716567f, 0.681718f },
{ 0.147621f, 0.716567f, 0.681718f },
{ 0.000000f, 0.525731f, 0.850651f },
{ 0.309017f, 0.500000f, 0.809017f },
{ 0.525731f, 0.000000f, 0.850651f },
{ 0.295242f, 0.000000f, 0.955423f },
{ 0.442863f, 0.238856f, 0.864188f },
{ 0.162460f, 0.262866f, 0.951056f },
{ -0.681718f, 0.147621f, 0.716567f },
{ -0.809017f, 0.309017f, 0.500000f },
{ -0.587785f, 0.425325f, 0.688191f },
{ -0.850651f, 0.525731f, 0.000000f },
{ -0.864188f, 0.442863f, 0.238856f },
{ -0.716567f, 0.681718f, 0.147621f },
{ -0.688191f, 0.587785f, 0.425325f },
{ -0.500000f, 0.809017f, 0.309017f },
{ -0.238856f, 0.864188f, 0.442863f },
{ -0.425325f, 0.688191f, 0.587785f },
{ -0.716567f, 0.681718f, -0.147621f },
{ -0.500000f, 0.809017f, -0.309017f },
{ -0.525731f, 0.850651f, 0.000000f },
{ 0.000000f, 0.850651f, -0.525731f },
{ -0.238856f, 0.864188f, -0.442863f },
{ 0.000000f, 0.955423f, -0.295242f },
{ -0.262866f, 0.951056f, -0.162460f },
{ 0.000000f, 1.000000f, 0.000000f },
{ 0.000000f, 0.955423f, 0.295242f },
{ -0.262866f, 0.951056f, 0.162460f },
{ 0.238856f, 0.864188f, 0.442863f },
{ 0.262866f, 0.951056f, 0.162460f },
{ 0.500000f, 0.809017f, 0.309017f },
{ 0.238856f, 0.864188f, -0.442863f },
{ 0.262866f, 0.951056f, -0.162460f },
{ 0.500000f, 0.809017f, -0.309017f },
{ 0.850651f, 0.525731f, 0.000000f },
{ 0.716567f, 0.681718f, 0.147621f },
{ 0.716567f, 0.681718f, -0.147621f },
{ 0.525731f, 0.850651f, 0.000000f },
{ 0.425325f, 0.688191f, 0.587785f },
{ 0.864188f, 0.442863f, 0.238856f },
{ 0.688191f, 0.587785f, 0.425325f },
{ 0.809017f, 0.309017f, 0.500000f },
{ 0.681718f, 0.147621f, 0.716567f },
{ 0.587785f, 0.425325f, 0.688191f },
{ 0.955423f, 0.295242f, 0.000000f },
{ 1.000000f, 0.000000f, 0.000000f },
{ 0.951056f, 0.162460f, 0.262866f },
{ 0.850651f, -0.525731f, 0.000000f },
{ 0.955423f, -0.295242f, 0.000000f },
{ 0.864188f, -0.442863f, 0.238856f },
{ 0.951056f, -0.162460f, 0.262866f },
{ 0.809017f, -0.309017f, 0.500000f },
{ 0.681718f, -0.147621f, 0.716567f },
{ 0.850651f, 0.000000f, 0.525731f },
{ 0.864188f, 0.442863f, -0.238856f },
{ 0.809017f, 0.309017f, -0.500000f },
{ 0.951056f, 0.162460f, -0.262866f },
{ 0.525731f, 0.000000f, -0.850651f },
{ 0.681718f, 0.147621f, -0.716567f },
{ 0.681718f, -0.147621f, -0.716567f },
{ 0.850651f, 0.000000f, -0.525731f },
{ 0.809017f, -0.309017f, -0.500000f },
{ 0.864188f, -0.442863f, -0.238856f },
{ 0.951056f, -0.162460f, -0.262866f },
{ 0.147621f, 0.716567f, -0.681718f },
{ 0.309017f, 0.500000f, -0.809017f },
{ 0.425325f, 0.688191f, -0.587785f },
{ 0.442863f, 0.238856f, -0.864188f },
{ 0.587785f, 0.425325f, -0.688191f },
{ 0.688191f, 0.587785f, -0.425325f },
{ -0.147621f, 0.716567f, -0.681718f },
{ -0.309017f, 0.500000f, -0.809017f },
{ 0.000000f, 0.525731f, -0.850651f },
{ -0.525731f, 0.000000f, -0.850651f },
{ -0.442863f, 0.238856f, -0.864188f },
{ -0.295242f, 0.000000f, -0.955423f },
{ -0.162460f, 0.262866f, -0.951056f },
{ 0.000000f, 0.000000f, -1.000000f },
{ 0.295242f, 0.000000f, -0.955423f },
{ 0.162460f, 0.262866f, -0.951056f },
{ -0.442863f, -0.238856f, -0.864188f },
{ -0.309017f, -0.500000f, -0.809017f },
{ -0.162460f, -0.262866f, -0.951056f },
{ 0.000000f, -0.850651f, -0.525731f },
{ -0.147621f, -0.716567f, -0.681718f },
{ 0.147621f, -0.716567f, -0.681718f },
{ 0.000000f, -0.525731f, -0.850651f },
{ 0.309017f, -0.500000f, -0.809017f },
{ 0.442863f, -0.238856f, -0.864188f },
{ 0.162460f, -0.262866f, -0.951056f },
{ 0.238856f, -0.864188f, -0.442863f },
{ 0.500000f, -0.809017f, -0.309017f },
{ 0.425325f, -0.688191f, -0.587785f },
{ 0.716567f, -0.681718f, -0.147621f },
{ 0.688191f, -0.587785f, -0.425325f },
{ 0.587785f, -0.425325f, -0.688191f },
{ 0.000000f, -0.955423f, -0.295242f },
{ 0.000000f, -1.000000f, 0.000000f },
{ 0.262866f, -0.951056f, -0.162460f },
{ 0.000000f, -0.850651f, 0.525731f },
{ 0.000000f, -0.955423f, 0.295242f },
{ 0.238856f, -0.864188f, 0.442863f },
{ 0.262866f, -0.951056f, 0.162460f },
{ 0.500000f, -0.809017f, 0.309017f },
{ 0.716567f, -0.681718f, 0.147621f },
{ 0.525731f, -0.850651f, 0.000000f },
{ -0.238856f, -0.864188f, -0.442863f },
{ -0.500000f, -0.809017f, -0.309017f },
{ -0.262866f, -0.951056f, -0.162460f },
{ -0.850651f, -0.525731f, 0.000000f },
{ -0.716567f, -0.681718f, -0.147621f },
{ -0.716567f, -0.681718f, 0.147621f },
{ -0.525731f, -0.850651f, 0.000000f },
{ -0.500000f, -0.809017f, 0.309017f },
{ -0.238856f, -0.864188f, 0.442863f },
{ -0.262866f, -0.951056f, 0.162460f },
{ -0.864188f, -0.442863f, 0.238856f },
{ -0.809017f, -0.309017f, 0.500000f },
{ -0.688191f, -0.587785f, 0.425325f },
{ -0.681718f, -0.147621f, 0.716567f },
{ -0.442863f, -0.238856f, 0.864188f },
{ -0.587785f, -0.425325f, 0.688191f },
{ -0.309017f, -0.500000f, 0.809017f },
{ -0.147621f, -0.716567f, 0.681718f },
{ -0.425325f, -0.688191f, 0.587785f },
{ -0.162460f, -0.262866f, 0.951056f },
{ 0.442863f, -0.238856f, 0.864188f },
{ 0.162460f, -0.262866f, 0.951056f },
{ 0.309017f, -0.500000f, 0.809017f },
{ 0.147621f, -0.716567f, 0.681718f },
{ 0.000000f, -0.525731f, 0.850651f },
{ 0.425325f, -0.688191f, 0.587785f },
{ 0.587785f, -0.425325f, 0.688191f },
{ 0.688191f, -0.587785f, 0.425325f },
{ -0.955423f, 0.295242f, 0.000000f },
{ -0.951056f, 0.162460f, 0.262866f },
{ -1.000000f, 0.000000f, 0.000000f },
{ -0.850651f, 0.000000f, 0.525731f },
{ -0.955423f, -0.295242f, 0.000000f },
{ -0.951056f, -0.162460f, 0.262866f },
{ -0.864188f, 0.442863f, -0.238856f },
{ -0.951056f, 0.162460f, -0.262866f },
{ -0.809017f, 0.309017f, -0.500000f },
{ -0.864188f, -0.442863f, -0.238856f },
{ -0.951056f, -0.162460f, -0.262866f },
{ -0.809017f, -0.309017f, -0.500000f },
{ -0.681718f, 0.147621f, -0.716567f },
{ -0.681718f, -0.147621f, -0.716567f },
{ -0.850651f, 0.000000f, -0.525731f },
{ -0.688191f, 0.587785f, -0.425325f },
{ -0.587785f, 0.425325f, -0.688191f },
{ -0.425325f, 0.688191f, -0.587785f },
{ -0.425325f, -0.688191f, -0.587785f },
{ -0.587785f, -0.425325f, -0.688191f },
{ -0.688191f, -0.587785f, -0.425325f }
};
#endif
Edit: one caveat - the exists() function is an Allegroism - you'll either need to strip it out or replace it if you're not using Allegro.
Last edited by a moderator: