]> de.git.xonotic.org Git - voretournament/voretournament.git/blobdiff - misc/mediasource/netradiant-src/libs/picomodel/pm_ase.c
Rename mediasource to source
[voretournament/voretournament.git] / misc / mediasource / netradiant-src / libs / picomodel / pm_ase.c
diff --git a/misc/mediasource/netradiant-src/libs/picomodel/pm_ase.c b/misc/mediasource/netradiant-src/libs/picomodel/pm_ase.c
deleted file mode 100644 (file)
index 31c448e..0000000
+++ /dev/null
@@ -1,1190 +0,0 @@
-/* -----------------------------------------------------------------------------
-
-PicoModel Library
-
-Copyright (c) 2002, Randy Reddig & seaw0lf
-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 aseMaterialList provided with the distribution.
-
-Neither the names of the copyright holders 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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.
-
------------------------------------------------------------------------------ */
-
-
-/* marker */
-#define PM_ASE_C
-
-/* uncomment when debugging this module */
-//#define DEBUG_PM_ASE 
-//#define DEBUG_PM_ASE_EX
-
-
-/* dependencies */
-#include "picointernal.h"
-
-#ifdef DEBUG_PM_ASE
-#include "time.h"
-#endif
-
-/* plain white */
-static picoColor_t white = { 255, 255, 255, 255 };
-
-/* jhefty - multi-subobject material support */
-
-/* Material/SubMaterial management */
-/* A material should have 1..n submaterials assigned to it */
-
-typedef struct aseSubMaterial_s
-{
-       struct aseSubMaterial_s* next;
-       int subMtlId;
-       picoShader_t* shader;
-       
-} aseSubMaterial_t;
-
-typedef struct aseMaterial_s
-{
-       struct aseMaterial_s* next;
-       struct aseSubMaterial_s* subMtls;
-       int mtlId;              
-} aseMaterial_t;
-
-/* Material/SubMaterial management functions */
-static aseMaterial_t* _ase_get_material ( aseMaterial_t* list , int mtlIdParent )
-{
-       aseMaterial_t* mtl = list;
-
-       while ( mtl )
-       {
-               if ( mtlIdParent == mtl->mtlId )
-               {
-                       break;
-               }
-               mtl = mtl->next;
-       }
-       return mtl;
-}
-
-static aseSubMaterial_t* _ase_get_submaterial ( aseMaterial_t* list, int  mtlIdParent , int subMtlId )
-{
-       aseMaterial_t* parent = _ase_get_material ( list , mtlIdParent );
-       aseSubMaterial_t* subMtl = NULL;
-
-       if ( !parent )
-       {
-               _pico_printf ( PICO_ERROR , "No ASE material exists with id %i\n" , mtlIdParent );
-               return NULL;
-       }
-
-       subMtl = parent->subMtls;
-       while ( subMtl )
-       {
-               if ( subMtlId == subMtl->subMtlId )
-               {
-                       break;
-               }
-               subMtl = subMtl->next;
-       }
-       return subMtl;
-}
-
-aseSubMaterial_t* _ase_get_submaterial_or_default ( aseMaterial_t* materials, int  mtlIdParent , int subMtlId )
-{
-       aseSubMaterial_t* subMtl = _ase_get_submaterial( materials, mtlIdParent, subMtlId );
-       if(subMtl != NULL)
-       {
-               return subMtl;
-       }
-
-       /* ydnar: trying default submaterial */
-       subMtl = _ase_get_submaterial( materials, mtlIdParent, 0 );
-       if( subMtl != NULL )
-       {
-               return subMtl;
-       }
-
-       _pico_printf( PICO_ERROR, "Could not find material/submaterial for id %d/%d\n", mtlIdParent, subMtlId );
-       return NULL;
-}
-
-
-
-
-static aseMaterial_t* _ase_add_material( aseMaterial_t **list, int mtlIdParent )
-{
-       aseMaterial_t *mtl = _pico_calloc( 1, sizeof( aseMaterial_t ) );
-       mtl->mtlId = mtlIdParent;
-       mtl->subMtls = NULL;
-       mtl->next = *list;
-       *list = mtl;
-
-       return mtl;
-}
-
-static aseSubMaterial_t* _ase_add_submaterial( aseMaterial_t **list, int mtlIdParent, int subMtlId, picoShader_t* shader )
-{
-       aseMaterial_t *parent = _ase_get_material( *list,  mtlIdParent );
-       aseSubMaterial_t *subMtl = _pico_calloc( 1, sizeof ( aseSubMaterial_t ) );
-
-       if ( !parent )
-       {
-               parent = _ase_add_material ( list , mtlIdParent );
-       }
-
-       subMtl->shader = shader;
-       subMtl->subMtlId = subMtlId;
-       subMtl->next = parent->subMtls;
-       parent->subMtls = subMtl;
-
-       return subMtl;
-}
-
-static void _ase_free_materials( aseMaterial_t **list )
-{
-       aseMaterial_t* mtl = *list;
-       aseSubMaterial_t* subMtl = NULL;
-
-       aseMaterial_t* mtlTemp = NULL;
-       aseSubMaterial_t* subMtlTemp = NULL;
-
-       while ( mtl )
-       {
-               subMtl = mtl->subMtls;
-               while ( subMtl )
-               {
-                       subMtlTemp = subMtl->next;
-                       _pico_free ( subMtl );
-                       subMtl = subMtlTemp;
-               }
-               mtlTemp = mtl->next;
-               _pico_free ( mtl );
-               mtl = mtlTemp;
-       }
-       (*list) = NULL;
-}
-
-#ifdef DEBUG_PM_ASE
-static void _ase_print_materials( aseMaterial_t *list )
-{
-       aseMaterial_t* mtl = list;
-       aseSubMaterial_t* subMtl = NULL;
-
-       while ( mtl )
-       {
-               _pico_printf ( PICO_NORMAL ,  "ASE Material %i" , mtl->mtlId );
-               subMtl = mtl->subMtls;
-               while ( subMtl )
-               {
-                       _pico_printf ( PICO_NORMAL ,  " -- ASE SubMaterial %i - %s\n" , subMtl->subMtlId , subMtl->shader->name );
-                       subMtl = subMtl->next;
-               }
-               mtl = mtl->next;
-       }
-}
-#endif //DEBUG_PM_ASE
-
-/* todo:
- * - apply material specific uv offsets to uv coordinates
- */
-
-/* _ase_canload:
- *  validates a 3dsmax ase model file.
- */
-static int _ase_canload( PM_PARAMS_CANLOAD )
-{
-       picoParser_t *p;
-       
-       
-       /* quick data length validation */
-       if( bufSize < 80 )
-               return PICO_PMV_ERROR_SIZE;
-       
-       /* create pico parser */
-       p = _pico_new_parser( (const picoByte_t*) buffer, bufSize );
-       if( p == NULL )
-               return PICO_PMV_ERROR_MEMORY;
-       
-       /* get first token */
-       if( _pico_parse_first( p ) == NULL)
-       {
-               return PICO_PMV_ERROR_IDENT;
-       }
-       
-       /* check first token */
-       if( _pico_stricmp( p->token, "*3dsmax_asciiexport" ) )
-       {
-               _pico_free_parser( p );
-               return PICO_PMV_ERROR_IDENT;
-       }
-       
-       /* free the pico parser object */
-       _pico_free_parser( p );
-       
-       /* file seems to be a valid ase file */
-       return PICO_PMV_OK;
-}
-
-typedef struct aseVertex_s aseVertex_t;
-struct aseVertex_s
-{
-       picoVec3_t xyz;
-       picoVec3_t normal;
-       picoIndex_t id;
-};
-
-typedef struct aseTexCoord_s aseTexCoord_t;
-struct aseTexCoord_s
-{
-       picoVec2_t texcoord;
-};
-
-typedef struct aseColor_s aseColor_t;
-struct aseColor_s
-{
-       picoColor_t color;
-};
-
-typedef struct aseFace_s aseFace_t;
-struct aseFace_s
-{
-       picoIndex_t indices[9];
-       picoIndex_t smoothingGroup;
-       picoIndex_t materialId;
-       picoIndex_t subMaterialId;
-};
-typedef aseFace_t* aseFacesIter_t;
-
-picoSurface_t* PicoModelFindOrAddSurface( picoModel_t *model, picoShader_t* shader )
-{
-       /* see if a surface already has the shader */
-       int i = 0;
-       for ( ; i < model->numSurfaces ; i++ )
-       {
-               picoSurface_t* workSurface = model->surface[i];
-               if ( workSurface->shader == shader )
-               {                       
-                       return workSurface;
-               }
-       }
-
-       /* no surface uses this shader yet, so create a new surface */
-
-       {
-               /* create a new surface in the model for the unique shader */
-               picoSurface_t* workSurface = PicoNewSurface(model);
-               if ( !workSurface )
-               {
-                       _pico_printf ( PICO_ERROR , "Could not allocate a new surface!\n" );
-                       return 0;
-               }
-
-               /* do surface setup */
-               PicoSetSurfaceType( workSurface, PICO_TRIANGLES );
-               PicoSetSurfaceName( workSurface, shader->name );
-               PicoSetSurfaceShader( workSurface, shader );
-
-               return workSurface;
-       }
-}
-
-/* _ase_submit_triangles - jhefty
- use the surface and the current face list to look up material/submaterial IDs
- and submit them to the model for proper processing
-
-The following still holds from ydnar's _ase_make_surface:
- indexes 0 1 2 = vert indexes
- indexes 3 4 5 = st indexes
- indexes 6 7 8 = color indexes (new)
-*/
-
-#if 0
-typedef picoIndex_t* picoIndexIter_t;
-
-typedef struct aseUniqueIndices_s aseUniqueIndices_t;
-struct aseUniqueIndices_s
-{
-       picoIndex_t* data;
-       picoIndex_t* last;
-
-       aseFace_t* faces;
-};
-
-size_t aseUniqueIndices_size(aseUniqueIndices_t* self)
-{
-       return self->last - self->data;
-}
-
-void aseUniqueIndices_reserve(aseUniqueIndices_t* self, picoIndex_t size)
-{
-       self->data = self->last = (picoIndex_t*)_pico_calloc(size, sizeof(picoIndex_t));
-}
-
-void aseUniqueIndices_clear(aseUniqueIndices_t* self)
-{
-       _pico_free(self->data);
-}
-
-void aseUniqueIndices_pushBack(aseUniqueIndices_t* self, picoIndex_t index)
-{
-       *self->last++ = index;
-}
-
-picoIndex_t aseFaces_getVertexIndex(aseFace_t* faces, picoIndex_t index)
-{
-       return faces[index / 3].indices[index % 3];
-}
-
-picoIndex_t aseFaces_getTexCoordIndex(aseFace_t* faces, picoIndex_t index)
-{
-       return faces[index / 3].indices[(index % 3) + 3];
-}
-
-picoIndex_t aseFaces_getColorIndex(aseFace_t* faces, picoIndex_t index)
-{
-       return faces[index / 3].indices[(index % 3) + 6];
-}
-
-int aseUniqueIndex_equal(aseFace_t* faces, picoIndex_t index, picoIndex_t other)
-{
-       return aseFaces_getVertexIndex(faces, index) == aseFaces_getVertexIndex(faces, other)
-               && aseFaces_getTexCoordIndex(faces, index) == aseFaces_getTexCoordIndex(faces, other)
-               && aseFaces_getColorIndex(faces, index) == aseFaces_getColorIndex(faces, other);
-}
-
-picoIndex_t aseUniqueIndices_insertUniqueVertex(aseUniqueIndices_t* self, picoIndex_t index)
-{
-       picoIndexIter_t i = self->data;
-       for(; i != self->last; ++i)
-       {
-               picoIndex_t other = (picoIndex_t)(i - self->data);
-               if(aseUniqueIndex_equal(self->faces, index, other))
-               {
-                       return other;
-               }
-       }
-
-       aseUniqueIndices_pushBack(self, index);
-       return (picoIndex_t)(aseUniqueIndices_size(self) - 1);
-}
-
-static void _ase_submit_triangles_unshared ( picoModel_t* model , aseMaterial_t* materials , aseVertex_t* vertices, aseTexCoord_t* texcoords, aseColor_t* colors, aseFace_t* faces, int numFaces, int meshHasNormals )
-{
-       aseFacesIter_t i = faces, end = faces + numFaces;
-
-       aseUniqueIndices_t indices;
-       aseUniqueIndices_t remap;
-       aseUniqueIndices_reserve(&indices, numFaces * 3);
-       aseUniqueIndices_reserve(&remap, numFaces * 3);
-       indices.faces = faces;
-
-       for(; i != end; ++i)
-       {
-               /* look up the shader for the material/submaterial pair */
-               aseSubMaterial_t* subMtl = _ase_get_submaterial_or_default( materials, (*i).materialId, (*i).subMaterialId );
-               if( subMtl == NULL )
-               {
-                       return;
-               }
-
-               {
-                       picoSurface_t* surface = PicoModelFindOrAddSurface(model, subMtl->shader);
-                       int j;
-                       /* we pull the data from the vertex, color and texcoord arrays using the face index data */
-                       for ( j = 0 ; j < 3 ; j ++ )
-                       {
-                               picoIndex_t index = (picoIndex_t)(((i - faces) * 3) + j);
-                               picoIndex_t size = (picoIndex_t)aseUniqueIndices_size(&indices);
-                               picoIndex_t unique = aseUniqueIndices_insertUniqueVertex(&indices, index);
-
-                               picoIndex_t numVertexes = PicoGetSurfaceNumVertexes(surface);
-                               picoIndex_t numIndexes = PicoGetSurfaceNumIndexes(surface);
-
-                               aseUniqueIndices_pushBack(&remap, numIndexes);
-
-                               PicoSetSurfaceIndex(surface, numIndexes, remap.data[unique]);
-
-                               if(unique == size)
-                               {
-                                       PicoSetSurfaceXYZ(surface, numVertexes, vertices[(*i).indices[j]].xyz);
-                                       PicoSetSurfaceNormal(surface, numVertexes, vertices[(*i).indices[j]].normal);
-                                       PicoSetSurfaceST(surface, 0, numVertexes, texcoords[(*i).indices[j + 3]].texcoord);
-
-                                       if ( (*i).indices[j + 6] >= 0 )
-                                       {
-                                               PicoSetSurfaceColor(surface, 0, numVertexes, colors[(*i).indices[j + 6]].color);
-                                       }
-                                       else
-                                       {
-                                               PicoSetSurfaceColor(surface, 0, numVertexes, white);
-                                       }
-
-                                       PicoSetSurfaceSmoothingGroup(surface, numVertexes, (vertices[(*i).indices[j]].id * (1 << 16)) + (*i).smoothingGroup);
-                               }
-                       }
-               }
-       }
-
-       aseUniqueIndices_clear(&indices);
-       aseUniqueIndices_clear(&remap);
-}
-
-#endif
-
-static void _ase_submit_triangles( picoModel_t* model , aseMaterial_t* materials , aseVertex_t* vertices, aseTexCoord_t* texcoords, aseColor_t* colors, aseFace_t* faces, int numFaces )
-{
-       aseFacesIter_t i = faces, end = faces + numFaces;
-       for(; i != end; ++i)
-       {
-               /* look up the shader for the material/submaterial pair */
-               aseSubMaterial_t* subMtl = _ase_get_submaterial_or_default( materials, (*i).materialId, (*i).subMaterialId );
-               if( subMtl == NULL )
-               {
-                       return;
-               }
-
-               {
-                       picoVec3_t* xyz[3];
-                       picoVec3_t* normal[3];
-                       picoVec2_t* st[3];
-                       picoColor_t* color[3];
-                       picoIndex_t smooth[3];
-                       int j;
-                       /* we pull the data from the vertex, color and texcoord arrays using the face index data */
-                       for ( j = 0 ; j < 3 ; j ++ )
-                       {
-                               xyz[j]    = &vertices[(*i).indices[j]].xyz;
-                               normal[j] = &vertices[(*i).indices[j]].normal;
-                               st[j]     = &texcoords[(*i).indices[j + 3]].texcoord;
-                       
-                               if( colors != NULL && (*i).indices[j + 6] >= 0 )
-                               {
-                                       color[j] = &colors[(*i).indices[j + 6]].color;
-                               }
-                               else
-                               {
-                                       color[j] = &white;
-                               }
-
-                               smooth[j] = (vertices[(*i).indices[j]].id * (1 << 16)) + (*i).smoothingGroup; /* don't merge vertices */
-                               
-                       }
-
-                       /* submit the triangle to the model */
-                       PicoAddTriangleToModel ( model , xyz , normal , 1 , st , 1 , color , subMtl->shader, smooth );
-               }
-       }
-}
-
-static void shadername_convert(char* shaderName)
-{
-  /* unix-style path separators */
-  char* s = shaderName;
-  for(; *s != '\0'; ++s)
-  {
-    if(*s == '\\')
-    {
-      *s = '/';
-    }
-  }
-}
-
-
-/* _ase_load:
- *  loads a 3dsmax ase model file.
-*/
-static picoModel_t *_ase_load( PM_PARAMS_LOAD )
-{
-       picoModel_t    *model;
-       picoParser_t   *p;
-       char                    lastNodeName[ 1024 ];
-
-       aseVertex_t* vertices = NULL;
-       aseTexCoord_t* texcoords = NULL;
-       aseColor_t* colors = NULL;
-       aseFace_t* faces = NULL;
-       int numVertices = 0;
-       int numFaces = 0;
-       int numTextureVertices = 0;
-       int numTextureVertexFaces = 0;
-       int numColorVertices = 0;
-       int numColorVertexFaces = 0;
-       int vertexId = 0;
-
-       aseMaterial_t* materials = NULL;
-
-#ifdef DEBUG_PM_ASE
-       clock_t start, finish;
-       double elapsed;
-       start = clock();
-#endif
-
-       /* helper */
-       #define _ase_error_return(m) \
-       { \
-               _pico_printf( PICO_ERROR,"%s in ASE, line %d.",m,p->curLine); \
-               _pico_free_parser( p ); \
-               PicoFreeModel( model ); \
-               return NULL; \
-       }
-       /* create a new pico parser */
-       p = _pico_new_parser( (const picoByte_t *)buffer,bufSize );
-       if (p == NULL) return NULL;
-
-       /* create a new pico model */
-       model = PicoNewModel();
-       if (model == NULL)
-       {
-               _pico_free_parser( p );
-               return NULL;
-       }
-       /* do model setup */
-       PicoSetModelFrameNum( model, frameNum );
-       PicoSetModelName( model, fileName );
-       PicoSetModelFileName( model, fileName );
-
-       /* initialize some stuff */
-       memset( lastNodeName,0,sizeof(lastNodeName) );
-
-       /* parse ase model file */
-       while( 1 )
-       {
-               /* get first token on line */
-               if (_pico_parse_first( p ) == NULL)
-                       break;
-
-               /* we just skip empty lines */
-               if (p->token == NULL || !strlen( p->token ))
-                       continue;
-
-               /* we skip invalid ase statements */
-               if (p->token[0] != '*' && p->token[0] != '{' && p->token[0] != '}')
-               {
-                       _pico_parse_skip_rest( p );
-                       continue;
-               }
-               /* remember node name */
-               if (!_pico_stricmp(p->token,"*node_name"))
-               {
-                       /* read node name */
-                       char *ptr = _pico_parse( p,0 );
-                       if (ptr == NULL)
-                               _ase_error_return("Node name parse error");
-
-                       /* remember node name */
-                       strncpy( lastNodeName,ptr,sizeof(lastNodeName) );
-               }
-               /* model mesh (originally contained within geomobject) */
-               else if (!_pico_stricmp(p->token,"*mesh"))
-               {
-                       /* finish existing surface */
-                       _ase_submit_triangles(model, materials, vertices, texcoords, colors, faces, numFaces);
-                       _pico_free(faces);
-                       _pico_free(vertices);
-                       _pico_free(texcoords);
-                       _pico_free(colors);
-               }
-               else if (!_pico_stricmp(p->token,"*mesh_numvertex"))
-               {
-                       if (!_pico_parse_int( p, &numVertices) )
-                               _ase_error_return("Missing MESH_NUMVERTEX value");
-
-                       vertices = _pico_calloc(numVertices, sizeof(aseVertex_t));
-               }
-               else if (!_pico_stricmp(p->token,"*mesh_numfaces"))
-               {
-                       if (!_pico_parse_int( p, &numFaces) )
-                               _ase_error_return("Missing MESH_NUMFACES value");
-
-                       faces = _pico_calloc(numFaces, sizeof(aseFace_t));
-               }
-               else if (!_pico_stricmp(p->token,"*mesh_numtvertex"))
-               {
-                       if (!_pico_parse_int( p, &numTextureVertices) )
-                               _ase_error_return("Missing MESH_NUMTVERTEX value");
-
-                       texcoords = _pico_calloc(numTextureVertices, sizeof(aseTexCoord_t));
-               }
-               else if (!_pico_stricmp(p->token,"*mesh_numtvfaces"))
-               {
-                       if (!_pico_parse_int( p, &numTextureVertexFaces) )
-                               _ase_error_return("Missing MESH_NUMTVFACES value");
-               }
-               else if (!_pico_stricmp(p->token,"*mesh_numcvertex"))
-               {
-                       if (!_pico_parse_int( p, &numColorVertices) )
-                               _ase_error_return("Missing MESH_NUMCVERTEX value");
-
-                       colors = _pico_calloc(numColorVertices, sizeof(aseColor_t));
-                       memset( colors, 255, numColorVertices * sizeof( aseColor_t ) ); /* ydnar: force colors to white initially */
-               }
-               else if (!_pico_stricmp(p->token,"*mesh_numcvfaces"))
-               {
-                       if (!_pico_parse_int( p, &numColorVertexFaces) )
-                               _ase_error_return("Missing MESH_NUMCVFACES value");
-               }
-               /* mesh material reference. this usually comes at the end of */
-               /* geomobjects after the mesh blocks. we must assume that the */
-               /* new mesh was already created so all we can do here is assign */
-               /* the material reference id (shader index) now. */
-               else if (!_pico_stricmp(p->token,"*material_ref"))
-               {
-                       int mtlId;
-
-                       /* get the material ref (0..n) */
-                       if (!_pico_parse_int( p,&mtlId) )
-                               _ase_error_return("Missing material reference ID");
-
-                       {
-                               int i = 0;
-                               /* fix up all of the aseFaceList in the surface to point to the parent material */
-                               /* we've already saved off their subMtl */
-                               for(; i < numFaces; ++i)
-                               {
-                                       faces[i].materialId = mtlId;
-                               }
-                       }
-               }
-               /* model mesh vertex */
-               else if (!_pico_stricmp(p->token,"*mesh_vertex"))
-               {
-                       int                     index;
-
-                       if( numVertices == 0 )
-                               _ase_error_return("Vertex parse error");
-
-                       /* get vertex data (orig: index +y -x +z) */
-                       if (!_pico_parse_int( p,&index ))
-                               _ase_error_return("Vertex parse error");
-                       if (!_pico_parse_vec( p,vertices[index].xyz ))
-                               _ase_error_return("Vertex parse error");
-
-                       vertices[index].id = vertexId++;
-               }
-               /* model mesh vertex normal */
-               else if (!_pico_stricmp(p->token,"*mesh_vertexnormal"))
-               {
-                       int                     index;
-
-                       if( numVertices == 0 )
-                               _ase_error_return("Vertex parse error");
-
-                       /* get vertex data (orig: index +y -x +z) */
-                       if (!_pico_parse_int( p,&index ))
-                               _ase_error_return("Vertex parse error");
-                       if (!_pico_parse_vec( p,vertices[index].normal ))
-                               _ase_error_return("Vertex parse error");
-               }
-               /* model mesh face */
-               else if (!_pico_stricmp(p->token,"*mesh_face"))
-               {
-                       picoIndex_t indexes[3];
-                       int index;
-                       
-                       if( numFaces == 0 )
-                               _ase_error_return("Face parse error");
-
-                       /* get face index */
-                       if (!_pico_parse_int( p,&index ))
-                               _ase_error_return("Face parse error");
-
-                       /* get 1st vertex index */
-                       _pico_parse( p,0 );
-                       if (!_pico_parse_int( p,&indexes[0] ))
-                               _ase_error_return("Face parse error");
-
-                       /* get 2nd vertex index */
-                       _pico_parse( p,0 );
-                       if (!_pico_parse_int( p,&indexes[1] ))
-                               _ase_error_return("Face parse error");
-
-                       /* get 3rd vertex index */
-                       _pico_parse( p,0 );
-                       if (!_pico_parse_int( p,&indexes[2] ))
-                               _ase_error_return("Face parse error");
-                       
-                       /* parse to the subMaterial ID */
-                       while ( 1 )
-                       {
-                               if (!_pico_parse (p,0)) /* EOL */
-                               {
-                                       break;
-                               }
-                               if (!_pico_stricmp (p->token,"*MESH_SMOOTHING" ))
-                               {
-                                       _pico_parse_int ( p , &faces[index].smoothingGroup );
-                               }
-                               if (!_pico_stricmp (p->token,"*MESH_MTLID" ))
-                               {
-                                       _pico_parse_int ( p , &faces[index].subMaterialId );
-                               }
-                       }
-                       
-                       faces[index].materialId = 0;
-                       faces[index].indices[0] = indexes[2];
-                       faces[index].indices[1] = indexes[1];
-                       faces[index].indices[2] = indexes[0];
-               }
-               /* model texture vertex */
-               else if (!_pico_stricmp(p->token,"*mesh_tvert"))
-               {
-                       int                     index;
-
-                       if( numVertices == 0 )
-                               _ase_error_return("Texture Vertex parse error");
-
-                       /* get uv vertex index */
-                       if (!_pico_parse_int( p,&index ) || index >= numTextureVertices)
-                               _ase_error_return("Texture vertex parse error");
-
-                       /* get uv vertex s */
-                       if (!_pico_parse_float( p,&texcoords[index].texcoord[0] ))
-                               _ase_error_return("Texture vertex parse error");
-
-                       /* get uv vertex t */
-                       if (!_pico_parse_float( p,&texcoords[index].texcoord[1] ))
-                               _ase_error_return("Texture vertex parse error");
-                       
-                       /* ydnar: invert t */
-                       texcoords[index].texcoord[ 1 ] = 1.0f - texcoords[index].texcoord[ 1 ];
-               }
-               /* ydnar: model mesh texture face */
-               else if( !_pico_stricmp( p->token, "*mesh_tface" ) )
-               {
-                       picoIndex_t indexes[3];
-                       int                     index;
-                       
-                       if( numFaces == 0 )
-                               _ase_error_return("Texture face parse error");
-                       
-                       /* get face index */
-                       if (!_pico_parse_int( p,&index ))
-                               _ase_error_return("Texture face parse error");
-                       
-                       /* get 1st vertex index */
-                       if (!_pico_parse_int( p,&indexes[0] ))
-                               _ase_error_return("Texture face parse error");
-                       
-                       /* get 2nd vertex index */
-                       if (!_pico_parse_int( p,&indexes[1] ))
-                               _ase_error_return("Texture face parse error");
-                       
-                       /* get 3rd vertex index */
-                       if (!_pico_parse_int( p,&indexes[2] ))
-                               _ase_error_return("Texture face parse error");
-
-                       faces[index].indices[3] = indexes[2];
-                       faces[index].indices[4] = indexes[1];
-                       faces[index].indices[5] = indexes[0];
-               }
-               /* model color vertex */
-               else if (!_pico_stricmp(p->token,"*mesh_vertcol"))
-               {
-                       int                     index;
-                       float           colorInput;
-
-                       if( numVertices == 0 )
-                               _ase_error_return("Color Vertex parse error");
-
-                       /* get color vertex index */
-                       if (!_pico_parse_int( p,&index ))
-                               _ase_error_return("Color vertex parse error");
-
-                       /* get R component */
-                       if (!_pico_parse_float( p,&colorInput ))
-                               _ase_error_return("Color vertex parse error");
-                       colors[index].color[0] = (picoByte_t)(colorInput * 255);
-
-                       /* get G component */
-                       if (!_pico_parse_float( p,&colorInput ))
-                               _ase_error_return("Color vertex parse error");
-                       colors[index].color[1] = (picoByte_t)(colorInput * 255);
-
-                       /* get B component */
-                       if (!_pico_parse_float( p,&colorInput ))
-                               _ase_error_return("Color vertex parse error");
-                       colors[index].color[2] = (picoByte_t)(colorInput * 255);
-                       
-                       /* leave alpha alone since we don't get any data from the ASE format */
-                       colors[index].color[3] = 255;
-               }
-               /* model color face */
-               else if (!_pico_stricmp(p->token,"*mesh_cface"))
-               {
-                       picoIndex_t indexes[3];
-                       int                     index;
-
-                       if( numFaces == 0 )
-                               _ase_error_return("Face parse error");
-
-                       /* get face index */
-                       if (!_pico_parse_int( p,&index ))
-                               _ase_error_return("Face parse error");
-
-                       /* get 1st cvertex index */
-                       //                      _pico_parse( p,0 );
-                       if (!_pico_parse_int( p,&indexes[0] ))
-                               _ase_error_return("Face parse error");
-
-                       /* get 2nd cvertex index */
-                       //                      _pico_parse( p,0 );
-                       if (!_pico_parse_int( p,&indexes[1] ))
-                               _ase_error_return("Face parse error");
-
-                       /* get 3rd cvertex index */
-                       //                      _pico_parse( p,0 );
-                       if (!_pico_parse_int( p,&indexes[2] ))
-                               _ase_error_return("Face parse error");
-
-                       faces[index].indices[6] = indexes[2];
-                       faces[index].indices[7] = indexes[1];
-                       faces[index].indices[8] = indexes[0];
-               }
-               /* model material */
-               else if( !_pico_stricmp( p->token, "*material" ) )
-               {
-                       aseSubMaterial_t*       subMaterial = NULL;
-                       picoShader_t            *shader = NULL;
-                       int                                     level = 1, index;
-                       char                            materialName[ 1024 ];
-                       float                           transValue = 0.0f, shineValue = 1.0f;
-                       picoColor_t                     ambientColor, diffuseColor, specularColor;
-                       char                            *mapname = NULL;
-                       int                                     subMtlId, subMaterialLevel = -1;
-                       
-                       
-                       /* get material index */
-                       _pico_parse_int( p,&index );
-                       
-                       /* check brace */
-                       if (!_pico_parse_check(p,1,"{"))
-                               _ase_error_return("Material missing opening brace");
-                       
-                       /* parse material block */
-                       while( 1 )
-                       {
-                               /* get next token */
-                               if (_pico_parse(p,1) == NULL) break;
-                               if (!strlen(p->token)) continue;
-
-                               /* handle levels */
-                               if (p->token[0] == '{') level++;
-                               if (p->token[0] == '}') level--;
-                               if (!level) break;
-
-                               if( level == subMaterialLevel )
-                               {
-                                       /* set material name */
-                                       _pico_first_token( materialName );
-          shadername_convert(materialName);
-                                       PicoSetShaderName( shader, materialName);
-
-                                       /* set shader's transparency */
-                                       PicoSetShaderTransparency( shader,transValue );
-
-                                       /* set shader's ambient color */
-                                       PicoSetShaderAmbientColor( shader,ambientColor );
-
-                                       /* set diffuse alpha to transparency */
-                                       diffuseColor[3] = (picoByte_t)( transValue * 255.0 );
-
-                                       /* set shader's diffuse color */
-                                       PicoSetShaderDiffuseColor( shader,diffuseColor );
-
-                                       /* set shader's specular color */
-                                       PicoSetShaderSpecularColor( shader,specularColor );
-
-                                       /* set shader's shininess */
-                                       PicoSetShaderShininess( shader,shineValue );
-
-                                       /* set material map name */
-                                       PicoSetShaderMapName( shader, mapname );
-
-                                       subMaterial = _ase_add_submaterial( &materials, index, subMtlId, shader );
-                                       subMaterialLevel = -1;
-                               }
-
-                               /* parse submaterial index */
-                               if (!_pico_stricmp(p->token,"*submaterial"))
-                               {                                                                                       
-                                       /* allocate new pico shader */
-                                       _pico_parse_int( p , &subMtlId );
-
-                                       shader = PicoNewShader( model );
-                                       if (shader == NULL)
-                                       {
-                                               PicoFreeModel( model );
-                                               return NULL;
-                                       }                       
-                                       subMaterialLevel = level;
-                               }
-                               /* parse material name */
-                               else if (!_pico_stricmp(p->token,"*material_name"))
-                               {
-                                       char* name = _pico_parse(p,0);
-                                       if ( name == NULL)
-                                               _ase_error_return("Missing material name");
-                                       
-                                       strcpy ( materialName , name );
-                                       /* skip rest and continue with next token */
-                                       _pico_parse_skip_rest( p );
-                                       continue;
-                               }
-                               /* parse material transparency */
-                               else if (!_pico_stricmp(p->token,"*material_transparency"))
-                               {
-                                       /* get transparency value from ase */
-                                       if (!_pico_parse_float( p,&transValue ))
-                                               _ase_error_return("Material transparency parse error");
-
-                                       /* skip rest and continue with next token */
-                                       _pico_parse_skip_rest( p );
-                                       continue;
-                               }
-                               /* parse material shininess */
-                               else if (!_pico_stricmp(p->token,"*material_shine"))
-                               {
-                                       /* remark:
-                                        * - not sure but instead of '*material_shine' i might
-                                        *   need to use '*material_shinestrength' */
-
-                                       /* get shine value from ase */
-                                       if (!_pico_parse_float( p,&shineValue ))
-                                               _ase_error_return("Material shine parse error");
-
-                                       /* scale ase shine range 0..1 to pico range 0..127 */
-                                       shineValue *= 128.0;
-
-                                       /* skip rest and continue with next token */
-                                       _pico_parse_skip_rest( p );
-                                       continue;
-                               }
-                               /* parse ambient material color */
-                               else if (!_pico_stricmp(p->token,"*material_ambient"))
-                               {
-                                       picoVec3_t  vec;
-                                       /* get r,g,b float values from ase */
-                                       if (!_pico_parse_vec( p,vec ))
-                                               _ase_error_return("Material color parse error");
-
-                                       /* setup 0..255 range color values */
-                                       ambientColor[ 0 ] = (int)( vec[ 0 ] * 255.0 );
-                                       ambientColor[ 1 ] = (int)( vec[ 1 ] * 255.0 );
-                                       ambientColor[ 2 ] = (int)( vec[ 2 ] * 255.0 );
-                                       ambientColor[ 3 ] = (int)( 255 );
-
-                                       /* skip rest and continue with next token */
-                                       _pico_parse_skip_rest( p );
-                                       continue;
-                               }
-                               /* parse diffuse material color */
-                               else if (!_pico_stricmp(p->token,"*material_diffuse"))
-                               {
-                                       picoVec3_t  vec;
-
-                                       /* get r,g,b float values from ase */
-                                       if (!_pico_parse_vec( p,vec ))
-                                               _ase_error_return("Material color parse error");
-
-                                       /* setup 0..255 range color */
-                                       diffuseColor[ 0 ] = (int)( vec[ 0 ] * 255.0 );
-                                       diffuseColor[ 1 ] = (int)( vec[ 1 ] * 255.0 );
-                                       diffuseColor[ 2 ] = (int)( vec[ 2 ] * 255.0 );
-                                       diffuseColor[ 3 ] = (int)( 255 );
-
-                                       /* skip rest and continue with next token */
-                                       _pico_parse_skip_rest( p );
-                                       continue;
-                               }
-                               /* parse specular material color */
-                               else if (!_pico_stricmp(p->token,"*material_specular"))
-                               {
-                                       picoVec3_t  vec;
-
-                                       /* get r,g,b float values from ase */
-                                       if (!_pico_parse_vec( p,vec ))
-                                               _ase_error_return("Material color parse error");
-
-                                       /* setup 0..255 range color */
-                                       specularColor[ 0 ] = (int)( vec[ 0 ] * 255 );
-                                       specularColor[ 1 ] = (int)( vec[ 1 ] * 255 );
-                                       specularColor[ 2 ] = (int)( vec[ 2 ] * 255 );
-                                       specularColor[ 3 ] = (int)( 255 );
-
-                                       /* skip rest and continue with next token */
-                                       _pico_parse_skip_rest( p );
-                                       continue;
-                               }
-                               /* material diffuse map */
-                               else if (!_pico_stricmp(p->token,"*map_diffuse") )
-                               {
-                                       int sublevel = 0;
-
-                                       /* parse material block */
-                                       while( 1 )
-                                       {
-                                               /* get next token */
-                                               if (_pico_parse(p,1) == NULL) break;
-                                               if (!strlen(p->token)) continue;
-                                               
-                                               /* handle levels */
-                                               if (p->token[0] == '{') sublevel++;
-                                               if (p->token[0] == '}') sublevel--;
-                                               if (!sublevel) break;
-                                               
-                                               /* parse diffuse map bitmap */
-                                               if (!_pico_stricmp(p->token,"*bitmap"))
-                                               {
-                                                       char* name = _pico_parse(p,0);
-                                                       if (name == NULL)
-                                                               _ase_error_return("Missing material map bitmap name");
-                                                       mapname = _pico_alloc ( strlen ( name ) + 1 );
-                                                       strcpy ( mapname, name );
-                                                       /* skip rest and continue with next token */
-                                                       _pico_parse_skip_rest( p );
-                                                       continue;
-                                               }
-                                       }
-                               }
-                               /* end map_diffuse block */
-                       }
-                       /* end material block */
-
-                       if( subMaterial == NULL )
-                       {
-                               /* allocate new pico shader */
-                               shader = PicoNewShader( model );
-                               if (shader == NULL)
-                               {
-                                       PicoFreeModel( model );
-                                       return NULL;
-                               }
-
-                               /* set material name */
-        shadername_convert(materialName);
-                               PicoSetShaderName( shader,materialName );
-
-                               /* set shader's transparency */
-                               PicoSetShaderTransparency( shader,transValue );
-
-                               /* set shader's ambient color */
-                               PicoSetShaderAmbientColor( shader,ambientColor );
-
-                               /* set diffuse alpha to transparency */
-                               diffuseColor[3] = (picoByte_t)( transValue * 255.0 );
-
-                               /* set shader's diffuse color */
-                               PicoSetShaderDiffuseColor( shader,diffuseColor );
-
-                               /* set shader's specular color */
-                               PicoSetShaderSpecularColor( shader,specularColor );
-
-                               /* set shader's shininess */
-                               PicoSetShaderShininess( shader,shineValue );
-
-                               /* set material map name */
-                               PicoSetShaderMapName( shader, mapname );
-
-        /* extract shadername from bitmap path */
-        if(mapname != NULL)
-        {
-          char* p = mapname;
-
-          /* convert to shader-name format */
-          shadername_convert(mapname);
-          {
-            /* remove extension */
-            char* last_period = strrchr(p, '.');
-            if(last_period != NULL)
-            {
-              *last_period = '\0';
-            }
-          }
-
-          /* find shader path */
-          for(; *p != '\0'; ++p)
-          {
-            if(_pico_strnicmp(p, "models/", 7) == 0 || _pico_strnicmp(p, "textures/", 9) == 0)
-            {
-              break;
-            }
-          }
-
-          if(*p != '\0')
-          {
-                                   /* set material name */
-                                   PicoSetShaderName( shader,p );
-          }
-        }
-
-        /* this is just a material with 1 submaterial */
-                               subMaterial = _ase_add_submaterial( &materials, index, 0, shader );
-                       }
-                       
-                       /* ydnar: free mapname */
-                       if( mapname != NULL )
-                               _pico_free( mapname );
-               }       // !_pico_stricmp ( "*material" )
-
-               /* skip unparsed rest of line and continue */
-               _pico_parse_skip_rest( p );
-       }
-       
-       /* ydnar: finish existing surface */
-       _ase_submit_triangles(model, materials, vertices, texcoords, colors, faces, numFaces);
-       _pico_free(faces);
-       _pico_free(vertices);
-       _pico_free(texcoords);
-       _pico_free(colors);
-
-#ifdef DEBUG_PM_ASE
-       _ase_print_materials(materials);
-       finish = clock();
-       elapsed = (double)(finish - start) / CLOCKS_PER_SEC;
-       _pico_printf( PICO_NORMAL, "Loaded model in in %-.2f second(s)\n", elapsed );
-#endif //DEBUG_PM_ASE
-
-       _ase_free_materials(&materials);
-
-  _pico_free_parser( p );
-
-       /* return allocated pico model */
-       return model;
-}
-
-/* pico file format module definition */
-const picoModule_t picoModuleASE =
-{
-       "1.0",                                  /* module version string */
-       "Autodesk 3DSMAX ASCII",        /* module display name */
-       "Jared Hefty, seaw0lf",                                 /* author's name */
-       "2003 Jared Hefty, 2002 seaw0lf",                               /* module copyright */
-       {
-               "ase",NULL,NULL,NULL    /* default extensions to use */
-       },
-       _ase_canload,                           /* validation routine */
-       _ase_load,                                      /* load routine */
-        NULL,                                          /* save validation routine */
-        NULL                                           /* save routine */
-};