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);
#endifmd2_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 }
    };
#endifEdit: 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: 
			
		
	
								
								
									
	
								
							
							 
	
 
 
		 
 
		 
 
		 
 
		