* fixed warning
[xonotic/netradiant.git] / libs / picomodel / pm_ase.c
index 985ea8a0fa0e2241191d6c144e78af2ebae79eca..c8465ce6cf01c391dbc38a30e7f309e3aaddcd46 100644 (file)
@@ -37,7 +37,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define PM_ASE_C
 
 /* uncomment when debugging this module */
-//#define DEBUG_PM_ASE 
+//#define DEBUG_PM_ASE
 //#define DEBUG_PM_ASE_EX
 
 
@@ -61,14 +61,14 @@ 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;              
+       int mtlId;
 } aseMaterial_t;
 
 /* Material/SubMaterial management functions */
@@ -110,28 +110,6 @@ static aseSubMaterial_t* _ase_get_submaterial ( aseMaterial_t* list, int  mtlIdP
        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 ) );
@@ -205,6 +183,68 @@ static void _ase_print_materials( aseMaterial_t *list )
 }
 #endif //DEBUG_PM_ASE
 
+/* ASE Face management */
+/* These are used to keep an association between a submaterial and a face definition */
+/* They are kept in parallel with the current picoSurface, */
+/* and are used by _ase_submit_triangles to lookup the proper material/submaterial IDs */
+typedef struct aseFace_s
+{
+       struct aseFace_s* next;
+       int mtlId;
+       int subMtlId;
+       int index[9];
+} aseFace_t;
+
+/* ASE Face management functions */
+void _ase_add_face( aseFace_t **list, aseFace_t **tail, aseFace_t *newFace )
+{
+       /* insert as head of list */
+       if ( !(*list) )
+       {
+               *list = newFace;
+       }
+       else
+       {
+               (*tail)->next = newFace;
+       }
+
+       *tail = newFace;
+       newFace->next = NULL;
+
+       //tag the color indices so we can detect them and apply the default color to them
+       newFace->index[6] = -1;
+       newFace->index[7] = -1;
+       newFace->index[8] = -1;
+}
+
+aseFace_t* _ase_get_face_for_index( aseFace_t *list, int index )
+{
+       int counter = 0;
+       aseFace_t* face = list;
+
+       while ( counter < index )
+       {
+               face = face->next;
+               counter++;
+       }
+       return face;
+}
+static void _ase_free_faces (aseFace_t** list, aseFace_t** tail )
+{
+       aseFace_t* face = *list;
+       aseFace_t* tempFace = NULL;
+
+       while ( face )
+       {
+               tempFace = face->next;
+               _pico_free ( face );
+               face = tempFace;
+       }
+
+       (*list) = NULL;
+       (*tail) = NULL;
+}
+
 /* todo:
  * - apply material specific uv offsets to uv coordinates
  */
@@ -215,102 +255,41 @@ static void _ase_print_materials( aseMaterial_t *list )
 static int _ase_canload( PM_PARAMS_CANLOAD )
 {
        picoParser_t *p;
-       
-       
+
+
        /* quick data length validation */
        if( bufSize < 80 )
                return PICO_PMV_ERROR_SIZE;
-       
+
        /* keep the friggin compiler happy */
        *fileName = *fileName;
-       
+
        /* create pico parser */
        p = _pico_new_parser( (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
@@ -322,197 +301,57 @@ The following still holds from ydnar's _ase_make_surface:
  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)
+static void _ase_submit_triangles ( picoSurface_t* surface , picoModel_t* model , aseMaterial_t* materials , aseFace_t* faces )
 {
-       _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)
+       aseFace_t* face;
+       aseSubMaterial_t* subMtl;
+       picoVec3_t* xyz[3];
+       picoVec3_t* normal[3];
+       picoVec2_t* st[3];
+       picoColor_t* color[3];
+       int i;
+
+       face = faces;
+       while ( face != NULL )
        {
                /* look up the shader for the material/submaterial pair */
-               aseSubMaterial_t* subMtl = _ase_get_submaterial_or_default( materials, (*i).materialId, (*i).subMaterialId );
+               subMtl = _ase_get_submaterial( materials, face->mtlId, face->subMtlId );
                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 ++ )
+                       /* ydnar: trying default submaterial */
+                       subMtl = _ase_get_submaterial( materials, face->mtlId, 0 );
+                       if( subMtl == NULL )
                        {
-                               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);
-                               }
+                               _pico_printf( PICO_ERROR, "Could not find material/submaterial for id %d/%d\n", face->mtlId, face->subMtlId );
+                               return;
                        }
                }
-       }
 
-       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 )
+               /* we pull the data from the surface using the facelist data */
+               for ( i = 0 ; i < 3 ; i ++ )
                {
-                       return;
-               }
+                       xyz[i]    = (picoVec3_t*) PicoGetSurfaceXYZ   ( surface, face->index[ i ] );
+                       normal[i] = (picoVec3_t*) PicoGetSurfaceNormal( surface, face->index[ i ] );
+                       st[i]     = (picoVec2_t*) PicoGetSurfaceST    ( surface, 0, face->index[ i + 3 ] );
 
-               {
-                       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 ++ )
+                       if ( face->index [ i + 6] >= 0 )
                        {
-                               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 */
-                               
+                               color[i]  = (picoColor_t*)PicoGetSurfaceColor ( surface, 0, face->index[ i + 6 ] );
+                       }
+                       else
+                       {
+                               color[i] = &white;
                        }
 
-                       /* 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 = '/';
-    }
-  }
-}
+               /* submit the triangle to the model */
+               PicoAddTriangleToModel ( model , xyz , normal , 1 , st , 1 , color , subMtl->shader );
 
+               /* advance to the next face */
+               face = face->next;
+       }
+}
 
 /* _ase_load:
  *  loads a 3dsmax ase model file.
@@ -520,21 +359,12 @@ static void shadername_convert(char* shaderName)
 static picoModel_t *_ase_load( PM_PARAMS_LOAD )
 {
        picoModel_t    *model;
+       picoSurface_t  *surface = NULL;
        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;
-
+       aseFace_t* facesTail = NULL;
        aseMaterial_t* materials = NULL;
 
 #ifdef DEBUG_PM_ASE
@@ -602,50 +432,17 @@ static picoModel_t *_ase_load( PM_PARAMS_LOAD )
                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");
+                       //_ase_make_surface( model, &surface );
+                       _ase_submit_triangles (surface, model ,materials,faces);
+                       _ase_free_faces (&faces,&facesTail);
 
-                       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");
+                       /* allocate new pico surface */
+                       surface = PicoNewSurface( NULL );
+                       if (surface == NULL)
+                       {
+                               PicoFreeModel( model );
+                               return NULL;
+                       }
                }
                /* mesh material reference. this usually comes at the end of */
                /* geomobjects after the mesh blocks. we must assume that the */
@@ -654,59 +451,72 @@ static picoModel_t *_ase_load( PM_PARAMS_LOAD )
                else if (!_pico_stricmp(p->token,"*material_ref"))
                {
                        int mtlId;
+                       aseFace_t* face;
+
+                       /* we must have a valid surface */
+                       if( surface == NULL )
+                               _ase_error_return("Missing mesh for material reference");
 
                        /* get the material ref (0..n) */
                        if (!_pico_parse_int( p,&mtlId) )
                                _ase_error_return("Missing material reference ID");
 
+                       /* fix up all of the aseFaceList in the surface to point to the parent material */
+                       /* we've already saved off their subMtl */
+                       face = faces;
+                       while ( face != NULL )
                        {
-                               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;
-                               }
+                               face->mtlId = mtlId;
+                               face = face->next;
                        }
                }
                /* model mesh vertex */
                else if (!_pico_stricmp(p->token,"*mesh_vertex"))
                {
+                       picoVec3_t      v;
                        int                     index;
 
-                       if( numVertices == 0 )
-                               _ase_error_return("Vertex parse error");
+                       /* we must have a valid surface */
+                       if( surface == NULL )
+                               continue;
 
                        /* 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 ))
+                       if (!_pico_parse_vec( p,v ))
                                _ase_error_return("Vertex parse error");
 
-                       vertices[index].id = vertexId++;
+                       /* set vertex */
+                       PicoSetSurfaceXYZ( surface,index,v );
                }
                /* model mesh vertex normal */
                else if (!_pico_stricmp(p->token,"*mesh_vertexnormal"))
                {
+                       picoVec3_t      v;
                        int                     index;
 
-                       if( numVertices == 0 )
-                               _ase_error_return("Vertex parse error");
+                       /* we must have a valid surface */
+                       if( surface == NULL )
+                               continue;
 
                        /* 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 ))
+                       if (!_pico_parse_vec( p,v ))
                                _ase_error_return("Vertex parse error");
+
+                       /* set vertex */
+                       PicoSetSurfaceNormal( surface,index,v );
                }
                /* 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");
+                       int                     index;
+
+                       /* we must have a valid surface */
+                       if( surface == NULL )
+                               continue;
 
                        /* get face index */
                        if (!_pico_parse_int( p,&index ))
@@ -726,120 +536,148 @@ static picoModel_t *_ase_load( PM_PARAMS_LOAD )
                        _pico_parse( p,0 );
                        if (!_pico_parse_int( p,&indexes[2] ))
                                _ase_error_return("Face parse error");
-                       
+
+                       /* set face indexes (note interleaved offset!) */
+                       PicoSetSurfaceIndex( surface, (index * 9 + 0), indexes[2] );
+                       PicoSetSurfaceIndex( surface, (index * 9 + 1), indexes[1] );
+                       PicoSetSurfaceIndex( surface, (index * 9 + 2), indexes[0] );
+
                        /* 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 );
-                               }
+                               _pico_parse (p,0);
                                if (!_pico_stricmp (p->token,"*MESH_MTLID" ))
                                {
-                                       _pico_parse_int ( p , &faces[index].subMaterialId );
+                                       aseFace_t* newFace;
+                                       int subMtlId;
+
+                                       _pico_parse_int ( p , &subMtlId );
+                                       newFace = _pico_calloc ( 1 , sizeof ( aseFace_t ));
+
+                                       /* we fix up the mtlId later when we parse the material_ref */
+                                       newFace->mtlId = 0;
+                                       newFace->subMtlId = subMtlId;
+                                       newFace->index[0] = indexes[2];
+                                       newFace->index[1] = indexes[1];
+                                       newFace->index[2] = indexes[0];
+
+                                       _ase_add_face ( &faces,&facesTail,newFace );
+                                       break;
                                }
                        }
-                       
-                       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"))
                {
+                       picoVec2_t      uv;
                        int                     index;
 
-                       if( numVertices == 0 )
-                               _ase_error_return("Texture Vertex parse error");
+                       /* we must have a valid surface */
+                       if( surface == NULL )
+                               continue;
 
                        /* get uv vertex index */
-                       if (!_pico_parse_int( p,&index ) || index >= numTextureVertices)
-                               _ase_error_return("Texture vertex parse error");
+                       if (!_pico_parse_int( p,&index ))
+                               _ase_error_return("UV vertex parse error");
 
                        /* get uv vertex s */
-                       if (!_pico_parse_float( p,&texcoords[index].texcoord[0] ))
-                               _ase_error_return("Texture vertex parse error");
+                       if (!_pico_parse_float( p,&uv[0] ))
+                               _ase_error_return("UV vertex parse error");
 
                        /* get uv vertex t */
-                       if (!_pico_parse_float( p,&texcoords[index].texcoord[1] ))
-                               _ase_error_return("Texture vertex parse error");
-                       
+                       if (!_pico_parse_float( p,&uv[1] ))
+                               _ase_error_return("UV vertex parse error");
+
                        /* ydnar: invert t */
-                       texcoords[index].texcoord[ 1 ] = 1.0f - texcoords[index].texcoord[ 1 ];
+                       uv[ 1 ] = 1.0f - uv[ 1 ];
+
+                       /* set texture vertex */
+                       PicoSetSurfaceST( surface,0,index,uv );
                }
                /* 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");
-                       
+                       aseFace_t* face;
+
+                       /* we must have a valid surface */
+                       if( surface == NULL )
+                               continue;
+
                        /* 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];
+                       /* set face indexes (note interleaved offset!) */
+                       PicoSetSurfaceIndex( surface, (index * 9 + 3), indexes[2] );
+                       PicoSetSurfaceIndex( surface, (index * 9 + 4), indexes[1] );
+                       PicoSetSurfaceIndex( surface, (index * 9 + 5), indexes[0] );
+
+                       face = _ase_get_face_for_index(faces,index);
+                       face->index[3] = indexes[2];
+                       face->index[4] = indexes[1];
+                       face->index[5] = indexes[0];
                }
                /* model color vertex */
                else if (!_pico_stricmp(p->token,"*mesh_vertcol"))
                {
+                       picoColor_t     color;
                        int                     index;
                        float           colorInput;
 
-                       if( numVertices == 0 )
-                               _ase_error_return("Color Vertex parse error");
+                       /* we must have a valid surface */
+                       if( surface == NULL )
+                               continue;
 
                        /* get color vertex index */
                        if (!_pico_parse_int( p,&index ))
-                               _ase_error_return("Color vertex parse error");
+                               _ase_error_return("UV 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);
+                               _ase_error_return("color vertex parse error");
+                       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);
+                               _ase_error_return("color vertex parse error");
+                       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);
-                       
+                               _ase_error_return("color vertex parse error");
+                       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;
+                       color[3] = 255;
+
+                       /* set texture vertex */
+                       PicoSetSurfaceColor( surface,0,index,color );
                }
                /* model color face */
                else if (!_pico_stricmp(p->token,"*mesh_cface"))
                {
                        picoIndex_t indexes[3];
                        int                     index;
+                       aseFace_t*  face;
 
-                       if( numFaces == 0 )
-                               _ase_error_return("Face parse error");
+                       /* we must have a valid surface */
+                       if( surface == NULL )
+                               continue;
 
                        /* get face index */
                        if (!_pico_parse_int( p,&index ))
@@ -860,30 +698,36 @@ static picoModel_t *_ase_load( PM_PARAMS_LOAD )
                        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];
+                       /* set face indexes (note interleaved offset!) */
+                       PicoSetSurfaceIndex( surface, (index * 9 + 6), indexes[2] );
+                       PicoSetSurfaceIndex( surface, (index * 9 + 7), indexes[1] );
+                       PicoSetSurfaceIndex( surface, (index * 9 + 8), indexes[0] );
+
+                       face = _ase_get_face_for_index(faces,index);
+                       face->index[6] = indexes[2];
+                       face->index[7] = indexes[1];
+                       face->index[8] = indexes[0];
                }
                /* model material */
                else if( !_pico_stricmp( p->token, "*material" ) )
                {
                        aseSubMaterial_t*       subMaterial = NULL;
-                       picoShader_t            *shader;
+                       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 )
                        {
@@ -899,8 +743,6 @@ static picoModel_t *_ase_load( PM_PARAMS_LOAD )
                                if( level == subMaterialLevel )
                                {
                                        /* set material name */
-                                       _pico_first_token( materialName );
-          shadername_convert(materialName);
                                        PicoSetShaderName( shader, materialName);
 
                                        /* set shader's transparency */
@@ -930,7 +772,7 @@ static picoModel_t *_ase_load( PM_PARAMS_LOAD )
 
                                /* parse submaterial index */
                                if (!_pico_stricmp(p->token,"*submaterial"))
-                               {                                                                                       
+                               {
                                        /* allocate new pico shader */
                                        _pico_parse_int( p , &subMtlId );
 
@@ -939,7 +781,7 @@ static picoModel_t *_ase_load( PM_PARAMS_LOAD )
                                        {
                                                PicoFreeModel( model );
                                                return NULL;
-                                       }                       
+                                       }
                                        subMaterialLevel = level;
                                }
                                /* parse material name */
@@ -948,7 +790,7 @@ static picoModel_t *_ase_load( PM_PARAMS_LOAD )
                                        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 );
@@ -1050,12 +892,12 @@ static picoModel_t *_ase_load( PM_PARAMS_LOAD )
                                                /* 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"))
                                                {
@@ -1085,7 +927,6 @@ static picoModel_t *_ase_load( PM_PARAMS_LOAD )
                                }
 
                                /* set material name */
-        shadername_convert(materialName);
                                PicoSetShaderName( shader,materialName );
 
                                /* set shader's transparency */
@@ -1109,42 +950,10 @@ static picoModel_t *_ase_load( PM_PARAMS_LOAD )
                                /* 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 */
+                               /* 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 );
@@ -1153,13 +962,11 @@ static picoModel_t *_ase_load( PM_PARAMS_LOAD )
                /* 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);
+//     _ase_make_surface( model, &surface );
+       _ase_submit_triangles (surface, model ,materials,faces);
+       _ase_free_faces (&faces,&facesTail);
 
 #ifdef DEBUG_PM_ASE
        _ase_print_materials(materials);
@@ -1170,8 +977,6 @@ static picoModel_t *_ase_load( PM_PARAMS_LOAD )
 
        _ase_free_materials(&materials);
 
-  _pico_free_parser( p );
-
        /* return allocated pico model */
        return model;
 }