]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - libs/picomodel/picomodel.c
Fix MSYS2 issues
[xonotic/netradiant.git] / libs / picomodel / picomodel.c
index d7790c37f91318ec4c2e365d26cc7a0a958b02c2..4526745c290b6a0d83acaeb8885b82599d988f83 100644 (file)
@@ -1,36 +1,36 @@
 /* -----------------------------------------------------------------------------
 
-PicoModel Library
+   PicoModel Library
 
-Copyright (c) 2002, Randy Reddig & seaw0lf
-All rights reserved.
+   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:
+   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 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 materials provided with the distribution.
+   Redistributions in binary form must reproduce the above copyright notice, this
+   list of conditions and the following disclaimer in the documentation and/or
+   other materials 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.
+   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.
+   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.
 
------------------------------------------------------------------------------ */
+   ----------------------------------------------------------------------------- */
 
 
 
@@ -45,12 +45,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 /*
-PicoInit()
-initializes the picomodel library
-*/
+   PicoInit()
+   initializes the picomodel library
+ */
 
-int PicoInit( void )
-{
+int PicoInit( void ){
        /* successfully initialized -sea */
        return 1;
 }
@@ -58,12 +57,11 @@ int PicoInit( void )
 
 
 /*
-PicoShutdown()
-shuts the pico model library down
-*/
+   PicoShutdown()
+   shuts the pico model library down
+ */
 
-void PicoShutdown( void )
-{
+void PicoShutdown( void ){
        /* do something interesting here in the future */
        return;
 }
@@ -71,12 +69,11 @@ void PicoShutdown( void )
 
 
 /*
-PicoError()
-returns last picomodel error code (see PME_* defines)
-*/
+   PicoError()
+   returns last picomodel error code (see PME_* defines)
+ */
 
-int PicoError( void )
-{
+int PicoError( void ){
        /* todo: do something here */
        return 0;
 }
@@ -84,192 +81,231 @@ int PicoError( void )
 
 
 /*
-PicoSetMallocFunc()
-sets the ptr to the malloc function
-*/
+   PicoSetMallocFunc()
+   sets the ptr to the malloc function
+ */
 
-void PicoSetMallocFunc( void *(*func)( size_t ) )
-{
-       if( func != NULL )
+void PicoSetMallocFunc( void *( *func )( size_t ) ){
+       if ( func != NULL ) {
                _pico_ptr_malloc = func;
+       }
 }
 
 
 
 /*
-PicoSetFreeFunc()
-sets the ptr to the free function
-*/
+   PicoSetFreeFunc()
+   sets the ptr to the free function
+ */
 
-void PicoSetFreeFunc( void (*func)( void* ) )
-{
-       if( func != NULL )
+void PicoSetFreeFunc( void ( *func )( void* ) ){
+       if ( func != NULL ) {
                _pico_ptr_free = func;
+       }
 }
 
 
 
 /*
-PicoSetLoadFileFunc()
-sets the ptr to the file load function
-*/
+   PicoSetLoadFileFunc()
+   sets the ptr to the file load function
+ */
 
-void PicoSetLoadFileFunc( void (*func)( char*, unsigned char**, int* ) )
-{
-       if( func != NULL )
+void PicoSetLoadFileFunc( void ( *func )( const char*, unsigned char**, int* ) ){
+       if ( func != NULL ) {
                _pico_ptr_load_file = func;
+       }
 }
 
 
 
 /*
-PicoSetFreeFileFunc()
-sets the ptr to the free function
-*/
+   PicoSetFreeFileFunc()
+   sets the ptr to the free function
+ */
 
-void PicoSetFreeFileFunc( void (*func)( void* ) )
-{
-       if( func != NULL )
+void PicoSetFreeFileFunc( void ( *func )( void* ) ){
+       if ( func != NULL ) {
                _pico_ptr_free_file = func;
+       }
 }
 
 
 
 /*
-PicoSetPrintFunc()
-sets the ptr to the print function
-*/
+   PicoSetPrintFunc()
+   sets the ptr to the print function
+ */
 
-void PicoSetPrintFunc( void (*func)( int, const char* ) )
-{
-       if( func != NULL )
+void PicoSetPrintFunc( void ( *func )( int, const char* ) ){
+       if ( func != NULL ) {
                _pico_ptr_print = func;
+       }
 }
 
 
 
+picoModel_t *PicoModuleLoadModel( const picoModule_t* pm, const char* fileName, picoByte_t* buffer, int bufSize, int frameNum ){
+       char                *modelFileName, *remapFileName;
+
+       /* see whether this module can load the model file or not */
+       if ( pm->canload( fileName, buffer, bufSize ) == PICO_PMV_OK ) {
+               /* use loader provided by module to read the model data */
+               picoModel_t* model = pm->load( fileName, frameNum, buffer, bufSize );
+               if ( model == NULL ) {
+                       _pico_free_file( buffer );
+                       return NULL;
+               }
+
+               /* assign pointer to file format module */
+               model->module = pm;
+
+               /* get model file name */
+               modelFileName = PicoGetModelFileName( model );
+
+               /* apply model remappings from <model>.remap */
+               if ( strlen( modelFileName ) ) {
+                       /* alloc copy of model file name */
+                       remapFileName = _pico_alloc( strlen( modelFileName ) + 20 );
+                       if ( remapFileName != NULL ) {
+                               /* copy model file name and change extension */
+                               strcpy( remapFileName, modelFileName );
+                               _pico_setfext( remapFileName, "remap" );
+
+                               /* try to remap model; we don't handle the result */
+                               PicoRemapModel( model, remapFileName );
+
+                               /* free the remap file name string */
+                               _pico_free( remapFileName );
+                       }
+               }
+
+               return model;
+       }
+
+       return NULL;
+}
+
 /*
-PicoLoadModel()
-the meat and potatoes function
-*/
+   PicoLoadModel()
+   the meat and potatoes function
+ */
+
+picoModel_t *PicoLoadModel( const char *fileName, int frameNum ){
+       const picoModule_t  **modules, *pm;
+       picoModel_t         *model;
+       picoByte_t          *buffer;
+       int bufSize;
 
-picoModel_t    *PicoLoadModel( char *fileName, int frameNum )
-{
-       const picoModule_t      **modules, *pm;
-       picoModel_t                     *model;
-       picoByte_t                      *buffer;
-       int                                     bufSize;
-       char                            *modelFileName, *remapFileName;
 
-       
        /* init */
        model = NULL;
-       
+
        /* make sure we've got a file name */
-       if( fileName == NULL )
-       {
+       if ( fileName == NULL ) {
                _pico_printf( PICO_ERROR, "PicoLoadModel: No filename given (fileName == NULL)" );
                return NULL;
        }
-       
+
        /* load file data (buffer is allocated by host app) */
        _pico_load_file( fileName, &buffer, &bufSize );
-       if( bufSize < 0 )
-       {
+       if ( bufSize < 0 ) {
                _pico_printf( PICO_ERROR, "PicoLoadModel: Failed loading model %s", fileName );
                return NULL;
        }
 
        /* get ptr to list of supported modules */
        modules = PicoModuleList( NULL );
-       
+
        /* run it through the various loader functions and try */
        /* to find a loader that fits the given file data */
-       for( ; *modules != NULL; modules++ )
+       for ( ; *modules != NULL; modules++ )
        {
                /* get module */
                pm = *modules;
-               
+
                /* sanity check */
-               if( pm == NULL)
+               if ( pm == NULL ) {
                        break;
+               }
 
                /* module must be able to load */
-               if( pm->canload == NULL || pm->load == NULL )
+               if ( pm->canload == NULL || pm->load == NULL ) {
                        continue;
-               
-               /* see whether this module can load the model file or not */
-               if( pm->canload( fileName, buffer, bufSize ) == PICO_PMV_OK )
-               {
-                       /* use loader provided by module to read the model data */
-                       model = pm->load( fileName, frameNum, buffer, bufSize );
-                       if( model == NULL )
-                       {
-                               _pico_free_file( buffer );
-                               return NULL;
-                       }
-                       
-                       /* assign pointer to file format module */
-                       model->module = pm;
-                       
-                       /* get model file name */
-                       modelFileName = PicoGetModelFileName( model );
-                       
-                       /* apply model remappings from <model>.remap */
-                       if( strlen( modelFileName ) )
-                       {
-                               /* alloc copy of model file name */
-                               remapFileName = _pico_alloc( strlen( modelFileName ) + 20 );
-                               if( remapFileName != NULL )
-                               {
-                                       /* copy model file name and change extension */
-                                       strcpy( remapFileName, modelFileName );
-                                       _pico_setfext( remapFileName, "remap" );
-
-                                       /* try to remap model; we don't handle the result */
-                                       PicoRemapModel( model, remapFileName );
+               }
 
-                                       /* free the remap file name string */
-                                       _pico_free( remapFileName );
-                               }
-                       }
-                       
+               model = PicoModuleLoadModel( pm, fileName, buffer, bufSize, frameNum );
+               if ( model != NULL ) {
                        /* model was loaded, so break out of loop */
                        break;
                }
        }
-       
+
        /* free memory used by file buffer */
-       if( buffer)
+       if ( buffer ) {
                _pico_free_file( buffer );
+       }
 
        /* return */
        return model;
 }
 
+picoModel_t *PicoModuleLoadModelStream( const picoModule_t* module, void* inputStream, PicoInputStreamReadFunc inputStreamRead, size_t streamLength, int frameNum, const char *fileName ){
+       picoModel_t         *model;
+       picoByte_t          *buffer;
+       int bufSize;
+
+
+       /* init */
+       model = NULL;
+
+       if ( inputStream == NULL ) {
+               _pico_printf( PICO_ERROR, "PicoLoadModel: invalid input stream (inputStream == NULL)" );
+               return NULL;
+       }
+
+       if ( inputStreamRead == NULL ) {
+               _pico_printf( PICO_ERROR, "PicoLoadModel: invalid input stream (inputStreamRead == NULL)" );
+               return NULL;
+       }
+
+       buffer = _pico_alloc( streamLength + 1 );
+
+       bufSize = (int)inputStreamRead( inputStream, buffer, streamLength );
+       buffer[bufSize] = '\0';
+
+       model = PicoModuleLoadModel( module, fileName, buffer, bufSize, frameNum );
+
+       if ( model != 0 ) {
+               _pico_free( buffer );
+       }
+
+       /* return */
+       return model;
+}
 
 
 /* ----------------------------------------------------------------------------
-models
----------------------------------------------------------------------------- */
+   models
+   ---------------------------------------------------------------------------- */
 
 /*
-PicoNewModel()
-creates a new pico model
-*/
+   PicoNewModel()
+   creates a new pico model
+ */
+
+picoModel_t *PicoNewModel( void ){
+       picoModel_t *model;
 
-picoModel_t *PicoNewModel( void )
-{
-       picoModel_t     *model;
-       
        /* allocate */
-       model = _pico_alloc( sizeof(picoModel_t) );
-       if( model == NULL )
+       model = _pico_alloc( sizeof( picoModel_t ) );
+       if ( model == NULL ) {
                return NULL;
+       }
 
        /* clear */
-       memset( model,0,sizeof(picoModel_t) );
-       
+       memset( model,0,sizeof( picoModel_t ) );
+
        /* model set up */
        _pico_zero_bounds( model->mins,model->maxs );
 
@@ -283,33 +319,38 @@ picoModel_t *PicoNewModel( void )
 
 
 /*
-PicoFreeModel()
-frees a model and all associated data
-*/
+   PicoFreeModel()
+   frees a model and all associated data
+ */
+
+void PicoFreeModel( picoModel_t *model ){
+       int i;
 
-void PicoFreeModel( picoModel_t *model )
-{
-       int                             i;
-       
 
        /* sanity check */
-       if( model == NULL )
+       if ( model == NULL ) {
                return;
-       
+       }
+
        /* free bits */
-       if( model->name )
+       if ( model->name ) {
                _pico_free( model->name );
-       
+       }
+
+       if ( model->fileName ) {
+               _pico_free( model->fileName );
+       }
+
        /* free shaders */
-       for( i = 0; i < model->numShaders; i++ )
+       for ( i = 0; i < model->numShaders; i++ )
                PicoFreeShader( model->shader[ i ] );
        free( model->shader );
-       
+
        /* free surfaces */
-       for( i = 0; i < model->numSurfaces; i++ )
+       for ( i = 0; i < model->numSurfaces; i++ )
                PicoFreeSurface( model->surface[ i ] );
        free( model->surface );
-       
+
        /* free the model */
        _pico_free( model );
 }
@@ -317,48 +358,54 @@ void PicoFreeModel( picoModel_t *model )
 
 
 /*
-PicoAdjustModel()
-adjusts a models's memory allocations to handle the requested sizes.
-will always grow, never shrink
-*/
+   PicoAdjustModel()
+   adjusts a models's memory allocations to handle the requested sizes.
+   will always grow, never shrink
+ */
 
-int PicoAdjustModel( picoModel_t *model, int numShaders, int numSurfaces )
-{
+int PicoAdjustModel( picoModel_t *model, int numShaders, int numSurfaces ){
        /* dummy check */
-       if( model == NULL )
+       if ( model == NULL ) {
                return 0;
-       
+       }
+
        /* bare minimums */
        /* sea: null surface/shader fix (1s=>0s) */
-       if( numShaders < 0 )
+       if ( numShaders < 0 ) {
                numShaders = 0;
-       if( numSurfaces < 0 )
+       }
+       if ( numSurfaces < 0 ) {
                numSurfaces = 0;
+       }
 
        /* additional shaders? */
-       while( numShaders > model->maxShaders )
+       while ( numShaders > model->maxShaders )
        {
                model->maxShaders += PICO_GROW_SHADERS;
-               if( !_pico_realloc( (void *) &model->shader, model->numShaders * sizeof( *model->shader ), model->maxShaders * sizeof( *model->shader ) ) )
+               if ( !_pico_realloc( (void *) &model->shader, model->numShaders * sizeof( *model->shader ), model->maxShaders * sizeof( *model->shader ) ) ) {
                        return 0;
+               }
        }
-       
+
        /* set shader count to higher */
-       if( numShaders > model->numShaders )
+       if ( numShaders > model->numShaders ) {
                model->numShaders = numShaders;
-       
+       }
+
        /* additional surfaces? */
-       while( numSurfaces > model->maxSurfaces )
+       while ( numSurfaces > model->maxSurfaces )
        {
                model->maxSurfaces += PICO_GROW_SURFACES;
-               if( !_pico_realloc( (void *) &model->surface, model->numSurfaces * sizeof( *model->surface ), model->maxSurfaces * sizeof( *model->surface ) ) )
+               if ( !_pico_realloc( (void *) &model->surface, model->numSurfaces * sizeof( *model->surface ), model->maxSurfaces * sizeof( *model->surface ) ) ) {
                        return 0;
+               }
        }
-       
+
        /* set shader count to higher */
-       if( numSurfaces > model->numSurfaces )
+       if ( numSurfaces > model->numSurfaces ) {
                model->numSurfaces = numSurfaces;
-       
+       }
+
        /* return ok */
        return 1;
 }
@@ -366,38 +413,38 @@ int PicoAdjustModel( picoModel_t *model, int numShaders, int numSurfaces )
 
 
 /* ----------------------------------------------------------------------------
-shaders
----------------------------------------------------------------------------- */
+   shaders
+   ---------------------------------------------------------------------------- */
 
 /*
-PicoNewShader()
-creates a new pico shader and returns its index. -sea
-*/
+   PicoNewShader()
+   creates a new pico shader and returns its index. -sea
+ */
+
+picoShader_t *PicoNewShader( picoModel_t *model ){
+       picoShader_t    *shader;
 
-picoShader_t *PicoNewShader( picoModel_t *model )
-{
-       picoShader_t    *shader;
-       
 
        /* allocate and clear */
-       shader = _pico_alloc( sizeof(picoShader_t) );
-       if( shader == NULL )
+       shader = _pico_alloc( sizeof( picoShader_t ) );
+       if ( shader == NULL ) {
                return NULL;
-       memset( shader, 0, sizeof(picoShader_t) );
-       
+       }
+       memset( shader, 0, sizeof( picoShader_t ) );
+
        /* attach it to the model */
-       if( model != NULL )
-       {
+       if ( model != NULL ) {
                /* adjust model */
-               if( !PicoAdjustModel( model, model->numShaders + 1, 0 ) )
-               {
+               if ( !PicoAdjustModel( model, model->numShaders + 1, 0 ) ) {
                        _pico_free( shader );
                        return NULL;
                }
+
                /* attach */
                model->shader[ model->numShaders - 1 ] = shader;
                shader->model = model;
        }
+
        /* setup default shader colors */
        _pico_set_color( shader->ambientColor,0,0,0,0 );
        _pico_set_color( shader->diffuseColor,255,255,255,1 );
@@ -414,22 +461,24 @@ picoShader_t *PicoNewShader( picoModel_t *model )
 
 
 /*
-PicoFreeShader()
-frees a shader and all associated data -sea
-*/
+   PicoFreeShader()
+   frees a shader and all associated data -sea
+ */
 
-void PicoFreeShader( picoShader_t *shader )
-{
+void PicoFreeShader( picoShader_t *shader ){
        /* dummy check */
-       if( shader == NULL )
+       if ( shader == NULL ) {
                return;
-       
+       }
+
        /* free bits */
-       if( shader->name )
+       if ( shader->name ) {
                _pico_free( shader->name );
-       if( shader->mapName )
+       }
+       if ( shader->mapName ) {
                _pico_free( shader->mapName );
-       
+       }
+
        /* free the shader */
        _pico_free( shader );
 }
@@ -437,37 +486,39 @@ void PicoFreeShader( picoShader_t *shader )
 
 
 /*
-PicoFindShader()
-finds a named shader in a model
-*/
+   PicoFindShader()
+   finds a named shader in a model
+ */
+
+picoShader_t *PicoFindShader( picoModel_t *model, char *name, int caseSensitive ){
+       int i;
+
 
-picoShader_t *PicoFindShader( picoModel_t *model, char *name, int caseSensitive )
-{
-       int             i;
-       
-       
        /* sanity checks */
-       if( model == NULL || name == NULL )     /* sea: null name fix */
+       if ( model == NULL || name == NULL ) { /* sea: null name fix */
                return NULL;
-       
+       }
+
        /* walk list */
-       for( i = 0; i < model->numShaders; i++ )
+       for ( i = 0; i < model->numShaders; i++ )
        {
                /* skip null shaders or shaders with null names */
-               if( model->shader[ i ] == NULL ||
-                       model->shader[ i ]->name == NULL )
+               if ( model->shader[ i ] == NULL ||
+                        model->shader[ i ]->name == NULL ) {
                        continue;
+               }
 
                /* compare the shader name with name we're looking for */
-               if( caseSensitive )
-               {
-                       if( !strcmp( name, model->shader[ i ]->name ) )
+               if ( caseSensitive ) {
+                       if ( !strcmp( name, model->shader[ i ]->name ) ) {
                                return model->shader[ i ];
+                       }
+               }
+               else if ( !_pico_stricmp( name, model->shader[ i ]->name ) ) {
+                       return model->shader[ i ];
                }
-               else if( !_pico_stricmp( name, model->shader[ i ]->name ) )
-                               return model->shader[ i ];
        }
-       
+
        /* named shader not found */
        return NULL;
 }
@@ -475,44 +526,42 @@ picoShader_t *PicoFindShader( picoModel_t *model, char *name, int caseSensitive
 
 
 /* ----------------------------------------------------------------------------
-surfaces
----------------------------------------------------------------------------- */
+   surfaces
+   ---------------------------------------------------------------------------- */
 
 /*
-PicoNewSurface()
-creates a new pico surface
-*/
+   PicoNewSurface()
+   creates a new pico surface
+ */
 
-picoSurface_t *PicoNewSurface( picoModel_t *model )
-{
-       picoSurface_t   *surface;
+picoSurface_t *PicoNewSurface( picoModel_t *model ){
+       picoSurface_t   *surface;
        char surfaceName[64];
-       
+
        /* allocate and clear */
        surface = _pico_alloc( sizeof( *surface ) );
-       if( surface == NULL )
+       if ( surface == NULL ) {
                return NULL;
+       }
        memset( surface, 0, sizeof( *surface ) );
-       
+
        /* attach it to the model */
-       if( model != NULL )
-       {
+       if ( model != NULL ) {
                /* adjust model */
-               if( !PicoAdjustModel( model, 0, model->numSurfaces + 1 ) )
-               {
+               if ( !PicoAdjustModel( model, 0, model->numSurfaces + 1 ) ) {
                        _pico_free( surface );
                        return NULL;
                }
-               
+
                /* attach */
                model->surface[ model->numSurfaces - 1 ] = surface;
                surface->model = model;
-               
+
                /* set default name */
                sprintf( surfaceName, "Unnamed_%d", model->numSurfaces );
                PicoSetSurfaceName( surface, surfaceName );
        }
-       
+
        /* return */
        return surface;
 }
@@ -520,32 +569,37 @@ picoSurface_t *PicoNewSurface( picoModel_t *model )
 
 
 /*
-PicoFreeSurface()
-frees a surface and all associated data
-*/
-void PicoFreeSurface( picoSurface_t *surface )
-{
-       int             i;
-       
-       
+   PicoFreeSurface()
+   frees a surface and all associated data
+ */
+void PicoFreeSurface( picoSurface_t *surface ){
+       int i;
+
+
        /* dummy check */
-       if( surface == NULL )
+       if ( surface == NULL ) {
                return;
-       
+       }
+
        /* free bits */
        _pico_free( surface->xyz );
        _pico_free( surface->normal );
+       _pico_free( surface->smoothingGroup );
        _pico_free( surface->index );
        _pico_free( surface->faceNormal );
-       
+
+       if ( surface->name ) {
+               _pico_free( surface->name );
+       }
+
        /* free arrays */
-       for( i = 0; i < surface->numSTArrays; i++ )
+       for ( i = 0; i < surface->numSTArrays; i++ )
                _pico_free( surface->st[ i ] );
        free( surface->st );
-       for( i = 0; i < surface->numColorArrays; i++ )
+       for ( i = 0; i < surface->numColorArrays; i++ )
                _pico_free( surface->color[ i ] );
        free( surface->color );
-       
+
        /* free the surface */
        _pico_free( surface );
 }
@@ -553,101 +607,119 @@ void PicoFreeSurface( picoSurface_t *surface )
 
 
 /*
-PicoAdjustSurface()
-adjusts a surface's memory allocations to handle the requested sizes.
-will always grow, never shrink
-*/
+   PicoAdjustSurface()
+   adjusts a surface's memory allocations to handle the requested sizes.
+   will always grow, never shrink
+ */
+
+int PicoAdjustSurface( picoSurface_t *surface, int numVertexes, int numSTArrays, int numColorArrays, int numIndexes, int numFaceNormals ){
+       int i;
+
 
-int PicoAdjustSurface( picoSurface_t *surface, int numVertexes, int numSTArrays, int numColorArrays, int numIndexes, int numFaceNormals )
-{
-       int             i;
-       
-       
        /* dummy check */
-       if( surface == NULL )
+       if ( surface == NULL ) {
                return 0;
-       
+       }
+
        /* bare minimums */
-       if( numVertexes < 1 )
+       if ( numVertexes < 1 ) {
                numVertexes = 1;
-       if( numSTArrays < 1 )
+       }
+       if ( numSTArrays < 1 ) {
                numSTArrays = 1;
-       if( numColorArrays < 1 )
+       }
+       if ( numColorArrays < 1 ) {
                numColorArrays = 1;
-       if( numIndexes < 1 )
+       }
+       if ( numIndexes < 1 ) {
                numIndexes = 1;
-       
+       }
+
        /* additional vertexes? */
-       while( numVertexes > surface->maxVertexes ) /* fix */
+       while ( numVertexes > surface->maxVertexes ) /* fix */
        {
                surface->maxVertexes += PICO_GROW_VERTEXES;
-               if( !_pico_realloc( (void *) &surface->xyz, surface->numVertexes * sizeof( *surface->xyz ), surface->maxVertexes * sizeof( *surface->xyz ) ) )
+               if ( !_pico_realloc( (void *) &surface->xyz, surface->numVertexes * sizeof( *surface->xyz ), surface->maxVertexes * sizeof( *surface->xyz ) ) ) {
                        return 0;
-               if( !_pico_realloc( (void *) &surface->normal, surface->numVertexes * sizeof( *surface->normal ), surface->maxVertexes * sizeof( *surface->normal ) ) )
-                       return 0;
-               for( i = 0; i < surface->numSTArrays; i++ )
-                       if( !_pico_realloc( (void*) &surface->st[ i ], surface->numVertexes * sizeof( *surface->st[ i ] ), surface->maxVertexes * sizeof( *surface->st[ i ] ) ) )
+               }
+               if ( !_pico_realloc( (void *) &surface->normal, surface->numVertexes * sizeof( *surface->normal ), surface->maxVertexes * sizeof( *surface->normal ) ) ) {
                        return 0;
-               for( i = 0; i < surface->numColorArrays; i++ )
-                       if( !_pico_realloc( (void*) &surface->color[ i ], surface->numVertexes * sizeof( *surface->color[ i ] ), surface->maxVertexes * sizeof( *surface->color[ i ] ) ) )
+               }
+               if ( !_pico_realloc( (void *) &surface->smoothingGroup, surface->numVertexes * sizeof( *surface->smoothingGroup ), surface->maxVertexes * sizeof( *surface->smoothingGroup ) ) ) {
                        return 0;
+               }
+               for ( i = 0; i < surface->numSTArrays; i++ )
+                       if ( !_pico_realloc( (void*) &surface->st[ i ], surface->numVertexes * sizeof( *surface->st[ i ] ), surface->maxVertexes * sizeof( *surface->st[ i ] ) ) ) {
+                               return 0;
+                       }
+               for ( i = 0; i < surface->numColorArrays; i++ )
+                       if ( !_pico_realloc( (void*) &surface->color[ i ], surface->numVertexes * sizeof( *surface->color[ i ] ), surface->maxVertexes * sizeof( *surface->color[ i ] ) ) ) {
+                               return 0;
+                       }
        }
-       
+
        /* set vertex count to higher */
-       if( numVertexes > surface->numVertexes )
+       if ( numVertexes > surface->numVertexes ) {
                surface->numVertexes = numVertexes;
-       
+       }
+
        /* additional st arrays? */
-       while( numSTArrays > surface->maxSTArrays ) /* fix */
+       while ( numSTArrays > surface->maxSTArrays ) /* fix */
        {
                surface->maxSTArrays += PICO_GROW_ARRAYS;
-               if( !_pico_realloc( (void*) &surface->st, surface->numSTArrays * sizeof( *surface->st ), surface->maxSTArrays * sizeof( *surface->st ) ) )
+               if ( !_pico_realloc( (void*) &surface->st, surface->numSTArrays * sizeof( *surface->st ), surface->maxSTArrays * sizeof( *surface->st ) ) ) {
                        return 0;
-               while( surface->numSTArrays < numSTArrays )
+               }
+               while ( surface->numSTArrays < numSTArrays )
                {
                        surface->st[ surface->numSTArrays ] = _pico_alloc( surface->maxVertexes * sizeof( *surface->st[ 0 ] ) );
                        memset( surface->st[ surface->numSTArrays ], 0, surface->maxVertexes * sizeof( *surface->st[ 0 ] ) );
                        surface->numSTArrays++;
                }
        }
-       
+
        /* additional color arrays? */
-       while( numColorArrays > surface->maxColorArrays ) /* fix */
+       while ( numColorArrays > surface->maxColorArrays ) /* fix */
        {
                surface->maxColorArrays += PICO_GROW_ARRAYS;
-               if( !_pico_realloc( (void*) &surface->color, surface->numColorArrays * sizeof( *surface->color ), surface->maxColorArrays * sizeof( *surface->color ) ) )
+               if ( !_pico_realloc( (void*) &surface->color, surface->numColorArrays * sizeof( *surface->color ), surface->maxColorArrays * sizeof( *surface->color ) ) ) {
                        return 0;
-               while( surface->numColorArrays < numColorArrays )
+               }
+               while ( surface->numColorArrays < numColorArrays )
                {
                        surface->color[ surface->numColorArrays ] = _pico_alloc( surface->maxVertexes * sizeof( *surface->color[ 0 ] ) );
                        memset( surface->color[ surface->numColorArrays ], 0, surface->maxVertexes * sizeof( *surface->color[ 0 ] ) );
                        surface->numColorArrays++;
                }
        }
-       
+
        /* additional indexes? */
-       while( numIndexes > surface->maxIndexes ) /* fix */
+       while ( numIndexes > surface->maxIndexes ) /* fix */
        {
                surface->maxIndexes += PICO_GROW_INDEXES;
-               if( !_pico_realloc( (void*) &surface->index, surface->numIndexes * sizeof( *surface->index ), surface->maxIndexes * sizeof( *surface->index ) ) )
+               if ( !_pico_realloc( (void*) &surface->index, surface->numIndexes * sizeof( *surface->index ), surface->maxIndexes * sizeof( *surface->index ) ) ) {
                        return 0;
+               }
        }
-       
+
        /* set index count to higher */
-       if( numIndexes > surface->numIndexes )
+       if ( numIndexes > surface->numIndexes ) {
                surface->numIndexes = numIndexes;
+       }
 
        /* additional face normals? */
-       while( numFaceNormals > surface->maxFaceNormals ) /* fix */
+       while ( numFaceNormals > surface->maxFaceNormals ) /* fix */
        {
                surface->maxFaceNormals += PICO_GROW_FACES;
-               if( !_pico_realloc( (void *) &surface->faceNormal, surface->numFaceNormals * sizeof( *surface->faceNormal ), surface->maxFaceNormals * sizeof( *surface->faceNormal ) ) )
+               if ( !_pico_realloc( (void *) &surface->faceNormal, surface->numFaceNormals * sizeof( *surface->faceNormal ), surface->maxFaceNormals * sizeof( *surface->faceNormal ) ) ) {
                        return 0;
+               }
        }
 
        /* set face normal count to higher */
-       if( numFaceNormals > surface->numFaceNormals )
+       if ( numFaceNormals > surface->numFaceNormals ) {
                surface->numFaceNormals = numFaceNormals;
+       }
 
        /* return ok */
        return 1;
@@ -658,29 +730,33 @@ int PicoAdjustSurface( picoSurface_t *surface, int numVertexes, int numSTArrays,
  *   Finds first matching named surface in a model.
  */
 picoSurface_t *PicoFindSurface(
-       picoModel_t *model, char *name, int caseSensitive )
-{
-       int             i;
+       picoModel_t *model, char *name, int caseSensitive ){
+       int i;
 
        /* sanity check */
-       if( model == NULL || name == NULL )
+       if ( model == NULL || name == NULL ) {
                return NULL;
-       
+       }
+
        /* walk list */
-       for( i = 0; i < model->numSurfaces; i++ )
+       for ( i = 0; i < model->numSurfaces; i++ )
        {
                /* skip null surfaces or surfaces with null names */
-               if( model->surface[ i ] == NULL ||
-                       model->surface[ i ]->name == NULL )
+               if ( model->surface[ i ] == NULL ||
+                        model->surface[ i ]->name == NULL ) {
                        continue;
+               }
 
                /* compare the surface name with name we're looking for */
-               if (caseSensitive) {
-                       if( !strcmp(name,model->surface[ i ]->name) )
+               if ( caseSensitive ) {
+                       if ( !strcmp( name,model->surface[ i ]->name ) ) {
                                return model->surface[ i ];
-               } else {
-                       if( !_pico_stricmp(name,model->surface[ i ]->name) )
+                       }
+               }
+               else {
+                       if ( !_pico_stricmp( name,model->surface[ i ]->name ) ) {
                                return model->surface[ i ];
+                       }
                }
        }
        /* named surface not found */
@@ -690,88 +766,92 @@ picoSurface_t *PicoFindSurface(
 
 
 /*----------------------------------------------------------------------------
-  PicoSet*() Setter Functions
-----------------------------------------------------------------------------*/
+   PicoSet*() Setter Functions
+   ----------------------------------------------------------------------------*/
 
-void PicoSetModelName( picoModel_t *model, char *name )
-{
-       if( model == NULL || name == NULL )
+void PicoSetModelName( picoModel_t *model, const char *name ){
+       if ( model == NULL || name == NULL ) {
                return;
-       if( model->name != NULL )
+       }
+       if ( model->name != NULL ) {
                _pico_free( model->name );
+       }
 
-       model->name = _pico_clone_alloc( name,-1 );
+       model->name = _pico_clone_alloc( name );
 }
 
 
 
-void PicoSetModelFileName( picoModel_t *model, char *fileName )
-{
-       if( model == NULL || fileName == NULL )
+void PicoSetModelFileName( picoModel_t *model, const char *fileName ){
+       if ( model == NULL || fileName == NULL ) {
                return;
-       if( model->fileName != NULL )
+       }
+       if ( model->fileName != NULL ) {
                _pico_free( model->fileName );
+       }
 
-       model->fileName = _pico_clone_alloc( fileName,-1 );
+       model->fileName = _pico_clone_alloc( fileName );
 }
 
 
 
-void PicoSetModelFrameNum( picoModel_t *model, int frameNum )
-{
-       if( model == NULL )
+void PicoSetModelFrameNum( picoModel_t *model, int frameNum ){
+       if ( model == NULL ) {
                return;
+       }
        model->frameNum = frameNum;
 }
 
 
 
-void PicoSetModelNumFrames( picoModel_t *model, int numFrames )
-{
-       if( model == NULL )
+void PicoSetModelNumFrames( picoModel_t *model, int numFrames ){
+       if ( model == NULL ) {
                return;
+       }
        model->numFrames = numFrames;
 }
 
 
 
-void PicoSetModelData( picoModel_t *model, void *data )
-{
-       if( model == NULL )
+void PicoSetModelData( picoModel_t *model, void *data ){
+       if ( model == NULL ) {
                return;
+       }
        model->data = data;
 }
 
 
 
-void PicoSetShaderName( picoShader_t *shader, char *name )
-{
-       if( shader == NULL || name == NULL )
+void PicoSetShaderName( picoShader_t *shader, char *name ){
+       if ( shader == NULL || name == NULL ) {
                return;
-       if( shader->name != NULL )
+       }
+       if ( shader->name != NULL ) {
                _pico_free( shader->name );
+       }
 
-       shader->name = _pico_clone_alloc( name,-1 );
+       shader->name = _pico_clone_alloc( name );
 }
 
 
 
-void PicoSetShaderMapName( picoShader_t *shader, char *mapName )
-{
-       if( shader == NULL || mapName == NULL )
+void PicoSetShaderMapName( picoShader_t *shader, char *mapName ){
+       if ( shader == NULL || mapName == NULL ) {
                return;
-       if( shader->mapName != NULL )
+       }
+       if ( shader->mapName != NULL ) {
                _pico_free( shader->mapName );
+       }
 
-       shader->mapName = _pico_clone_alloc( mapName,-1 );
+       shader->mapName = _pico_clone_alloc( mapName );
 }
 
 
 
-void PicoSetShaderAmbientColor( picoShader_t *shader, picoColor_t color )
-{
-       if( shader == NULL || color == NULL )
+void PicoSetShaderAmbientColor( picoShader_t *shader, picoColor_t color ){
+       if ( shader == NULL || color == NULL ) {
                return;
+       }
        shader->ambientColor[ 0 ] = color[ 0 ];
        shader->ambientColor[ 1 ] = color[ 1 ];
        shader->ambientColor[ 2 ] = color[ 2 ];
@@ -780,10 +860,10 @@ void PicoSetShaderAmbientColor( picoShader_t *shader, picoColor_t color )
 
 
 
-void PicoSetShaderDiffuseColor( picoShader_t *shader, picoColor_t color )
-{
-       if( shader == NULL || color == NULL )
+void PicoSetShaderDiffuseColor( picoShader_t *shader, picoColor_t color ){
+       if ( shader == NULL || color == NULL ) {
                return;
+       }
        shader->diffuseColor[ 0 ] = color[ 0 ];
        shader->diffuseColor[ 1 ] = color[ 1 ];
        shader->diffuseColor[ 2 ] = color[ 2 ];
@@ -792,10 +872,10 @@ void PicoSetShaderDiffuseColor( picoShader_t *shader, picoColor_t color )
 
 
 
-void PicoSetShaderSpecularColor( picoShader_t *shader, picoColor_t color )
-{
-       if( shader == NULL || color == NULL )
+void PicoSetShaderSpecularColor( picoShader_t *shader, picoColor_t color ){
+       if ( shader == NULL || color == NULL ) {
                return;
+       }
        shader->specularColor[ 0 ] = color[ 0 ];
        shader->specularColor[ 1 ] = color[ 1 ];
        shader->specularColor[ 2 ] = color[ 2 ];
@@ -804,117 +884,127 @@ void PicoSetShaderSpecularColor( picoShader_t *shader, picoColor_t color )
 
 
 
-void PicoSetShaderTransparency( picoShader_t *shader, float value )
-{
-       if( shader == NULL )
+void PicoSetShaderTransparency( picoShader_t *shader, float value ){
+       if ( shader == NULL ) {
                return;
+       }
        shader->transparency = value;
 
        /* cap to 0..1 range */
-       if (shader->transparency < 0.0)
+       if ( shader->transparency < 0.0 ) {
                shader->transparency = 0.0;
-       if (shader->transparency > 1.0)
+       }
+       if ( shader->transparency > 1.0 ) {
                shader->transparency = 1.0;
+       }
 }
 
 
 
-void PicoSetShaderShininess( picoShader_t *shader, float value )
-{
-       if( shader == NULL )
+void PicoSetShaderShininess( picoShader_t *shader, float value ){
+       if ( shader == NULL ) {
                return;
+       }
        shader->shininess = value;
 
        /* cap to 0..127 range */
-       if (shader->shininess < 0.0)
+       if ( shader->shininess < 0.0 ) {
                shader->shininess = 0.0;
-       if (shader->shininess > 127.0)
+       }
+       if ( shader->shininess > 127.0 ) {
                shader->shininess = 127.0;
+       }
 }
 
 
 
-void PicoSetSurfaceData( picoSurface_t *surface, void *data )
-{
-       if( surface == NULL )
+void PicoSetSurfaceData( picoSurface_t *surface, void *data ){
+       if ( surface == NULL ) {
                return;
+       }
        surface->data = data;
 }
 
 
 
-void PicoSetSurfaceType( picoSurface_t *surface, picoSurfaceType_t type )
-{
-       if( surface == NULL )
+void PicoSetSurfaceType( picoSurface_t *surface, picoSurfaceType_t type ){
+       if ( surface == NULL ) {
                return;
+       }
        surface->type = type;
 }
 
 
 
-void PicoSetSurfaceName( picoSurface_t *surface, char *name )
-{
-       if( surface == NULL || name == NULL )
+void PicoSetSurfaceName( picoSurface_t *surface, const char *name ){
+       if ( surface == NULL || name == NULL ) {
                return;
-       if( surface->name != NULL )
+       }
+       if ( surface->name != NULL ) {
                _pico_free( surface->name );
+       }
 
-       surface->name = _pico_clone_alloc( name,-1 );
+       surface->name = _pico_clone_alloc( name );
 }
 
 
 
-void PicoSetSurfaceShader( picoSurface_t *surface, picoShader_t *shader )
-{
-       if( surface == NULL )
+void PicoSetSurfaceShader( picoSurface_t *surface, picoShader_t *shader ){
+       if ( surface == NULL ) {
                return;
+       }
        surface->shader = shader;
 }
 
 
 
-void PicoSetSurfaceXYZ( picoSurface_t *surface, int num, picoVec3_t xyz )
-{
-       if( surface == NULL || num < 0 || xyz == NULL )
+void PicoSetSurfaceXYZ( picoSurface_t *surface, int num, picoVec3_t xyz ){
+       if ( surface == NULL || num < 0 || xyz == NULL ) {
                return;
-       if( !PicoAdjustSurface( surface, num + 1, 0, 0, 0, 0 ) )
+       }
+       if ( !PicoAdjustSurface( surface, num + 1, 0, 0, 0, 0 ) ) {
                return;
+       }
        _pico_copy_vec( xyz, surface->xyz[ num ] );
-       if( surface->model != NULL )
+       if ( surface->model != NULL ) {
                _pico_expand_bounds( xyz, surface->model->mins, surface->model->maxs );
+       }
 }
 
 
 
-void PicoSetSurfaceNormal( picoSurface_t *surface, int num, picoVec3_t normal )
-{
-       if( surface == NULL || num < 0 || normal == NULL )
+void PicoSetSurfaceNormal( picoSurface_t *surface, int num, picoVec3_t normal ){
+       if ( surface == NULL || num < 0 || normal == NULL ) {
                return;
-       if( !PicoAdjustSurface( surface, num + 1, 0, 0, 0, 0 ) )
+       }
+       if ( !PicoAdjustSurface( surface, num + 1, 0, 0, 0, 0 ) ) {
                return;
+       }
        _pico_copy_vec( normal, surface->normal[ num ] );
 }
 
 
 
-void PicoSetSurfaceST( picoSurface_t *surface, int array, int num, picoVec2_t st )
-{
-       if( surface == NULL || num < 0 || st == NULL )
+void PicoSetSurfaceST( picoSurface_t *surface, int array, int num, picoVec2_t st ){
+       if ( surface == NULL || num < 0 || st == NULL ) {
                return;
-       if( !PicoAdjustSurface( surface, num + 1, array + 1, 0, 0, 0 ) )
+       }
+       if ( !PicoAdjustSurface( surface, num + 1, array + 1, 0, 0, 0 ) ) {
                return;
+       }
        surface->st[ array ][ num ][ 0 ] = st[ 0 ];
        surface->st[ array ][ num ][ 1 ] = st[ 1 ];
 }
 
 
 
-void PicoSetSurfaceColor( picoSurface_t *surface, int array, int num, picoColor_t color )
-{
-       if( surface == NULL || num < 0 || color == NULL )
+void PicoSetSurfaceColor( picoSurface_t *surface, int array, int num, picoColor_t color ){
+       if ( surface == NULL || num < 0 || color == NULL ) {
                return;
-       if( !PicoAdjustSurface( surface, num + 1, 0, array + 1, 0, 0 ) )
+       }
+       if ( !PicoAdjustSurface( surface, num + 1, 0, array + 1, 0, 0 ) ) {
                return;
+       }
        surface->color[ array ][ num ][ 0 ] = color[ 0 ];
        surface->color[ array ][ num ][ 1 ] = color[ 1 ];
        surface->color[ array ][ num ][ 2 ] = color[ 2 ];
@@ -923,465 +1013,492 @@ void PicoSetSurfaceColor( picoSurface_t *surface, int array, int num, picoColor_
 
 
 
-void PicoSetSurfaceIndex( picoSurface_t *surface, int num, picoIndex_t index )
-{
-       if( surface == NULL || num < 0 )
+void PicoSetSurfaceIndex( picoSurface_t *surface, int num, picoIndex_t index ){
+       if ( surface == NULL || num < 0 ) {
                return;
-       if( !PicoAdjustSurface( surface, 0, 0, 0, num + 1, 0 ) )
+       }
+       if ( !PicoAdjustSurface( surface, 0, 0, 0, num + 1, 0 ) ) {
                return;
+       }
        surface->index[ num ] = index;
 }
 
 
 
-void PicoSetSurfaceIndexes( picoSurface_t *surface, int num, picoIndex_t *index, int count )
-{
-       if( num < 0 || index == NULL || count < 1 )
+void PicoSetSurfaceIndexes( picoSurface_t *surface, int num, picoIndex_t *index, int count ){
+       if ( num < 0 || index == NULL || count < 1 ) {
                return;
-       if( !PicoAdjustSurface( surface, 0, 0, 0, num + count, 0 ) )
+       }
+       if ( !PicoAdjustSurface( surface, 0, 0, 0, num + count, 0 ) ) {
                return;
+       }
        memcpy( &surface->index[ num ], index, count * sizeof( surface->index[ num ] ) );
 }
 
 
 
-void PicoSetFaceNormal( picoSurface_t *surface, int num, picoVec3_t normal )
-{
-       if( surface == NULL || num < 0 || normal == NULL )
+void PicoSetFaceNormal( picoSurface_t *surface, int num, picoVec3_t normal ){
+       if ( surface == NULL || num < 0 || normal == NULL ) {
                return;
-       if( !PicoAdjustSurface( surface, 0, 0, 0, 0, num + 1 ) )
+       }
+       if ( !PicoAdjustSurface( surface, 0, 0, 0, 0, num + 1 ) ) {
                return;
+       }
        _pico_copy_vec( normal, surface->faceNormal[ num ] );
 }
 
 
-void PicoSetSurfaceSpecial( picoSurface_t *surface, int num, int special )
-{
-       if( surface == NULL || num < 0 || num >= PICO_MAX_SPECIAL )
+void PicoSetSurfaceSmoothingGroup( picoSurface_t *surface, int num, picoIndex_t smoothingGroup ){
+       if ( num < 0 ) {
+               return;
+       }
+       if ( !PicoAdjustSurface( surface, num + 1, 0, 0, 0, 0 ) ) {
                return;
+       }
+       surface->smoothingGroup[ num ] = smoothingGroup;
+}
+
+
+void PicoSetSurfaceSpecial( picoSurface_t *surface, int num, int special ){
+       if ( surface == NULL || num < 0 || num >= PICO_MAX_SPECIAL ) {
+               return;
+       }
        surface->special[ num ] = special;
 }
 
 
 
 /*----------------------------------------------------------------------------
-  PicoGet*() Getter Functions
-----------------------------------------------------------------------------*/
+   PicoGet*() Getter Functions
+   ----------------------------------------------------------------------------*/
 
-char *PicoGetModelName( picoModel_t *model )
-{
-       if( model == NULL )
+char *PicoGetModelName( picoModel_t *model ){
+       if ( model == NULL ) {
                return NULL;
-       if( model->name == NULL)
+       }
+       if ( model->name == NULL ) {
                return (char*) "";
+       }
        return model->name;
 }
 
 
 
-char *PicoGetModelFileName( picoModel_t *model )
-{
-       if( model == NULL )
+char *PicoGetModelFileName( picoModel_t *model ){
+       if ( model == NULL ) {
                return NULL;
-       if( model->fileName == NULL)
+       }
+       if ( model->fileName == NULL ) {
                return (char*) "";
+       }
        return model->fileName;
 }
 
 
 
-int PicoGetModelFrameNum( picoModel_t *model )
-{
-       if( model == NULL )
+int PicoGetModelFrameNum( picoModel_t *model ){
+       if ( model == NULL ) {
                return 0;
+       }
        return model->frameNum;
 }
 
 
 
-int PicoGetModelNumFrames( picoModel_t *model )
-{
-       if( model == NULL )
+int PicoGetModelNumFrames( picoModel_t *model ){
+       if ( model == NULL ) {
                return 0;
+       }
        return model->numFrames;
 }
 
 
 
-void *PicoGetModelData( picoModel_t *model )
-{
-       if( model == NULL )
+void *PicoGetModelData( picoModel_t *model ){
+       if ( model == NULL ) {
                return NULL;
+       }
        return model->data;
 }
 
 
 
-int PicoGetModelNumShaders( picoModel_t *model )
-{
-       if( model == NULL )
+int PicoGetModelNumShaders( picoModel_t *model ){
+       if ( model == NULL ) {
                return 0;
+       }
        return model->numShaders;
 }
 
 
 
-picoShader_t *PicoGetModelShader( picoModel_t *model, int num )
-{
+picoShader_t *PicoGetModelShader( picoModel_t *model, int num ){
        /* a few sanity checks */
-       if( model == NULL )
+       if ( model == NULL ) {
                return NULL;
-       if( model->shader == NULL)
+       }
+       if ( model->shader == NULL ) {
                return NULL;
-       if( num < 0 || num >= model->numShaders )
+       }
+       if ( num < 0 || num >= model->numShaders ) {
                return NULL;
-       
+       }
+
        /* return the shader */
        return model->shader[ num ];
 }
 
 
 
-int PicoGetModelNumSurfaces( picoModel_t *model )
-{
-       if( model == NULL )
+int PicoGetModelNumSurfaces( picoModel_t *model ){
+       if ( model == NULL ) {
                return 0;
+       }
        return model->numSurfaces;
 }
 
 
 
-picoSurface_t *PicoGetModelSurface( picoModel_t *model, int num )
-{
+picoSurface_t *PicoGetModelSurface( picoModel_t *model, int num ){
        /* a few sanity checks */
-       if( model == NULL )
+       if ( model == NULL ) {
                return NULL;
-       if( model->surface == NULL)
+       }
+       if ( model->surface == NULL ) {
                return NULL;
-       if( num < 0 || num >= model->numSurfaces )
+       }
+       if ( num < 0 || num >= model->numSurfaces ) {
                return NULL;
-       
+       }
+
        /* return the surface */
        return model->surface[ num ];
 }
 
 
 
-int PicoGetModelTotalVertexes( picoModel_t *model )
-{
-       int             i, count;
-       
-       
-       if( model == NULL )
+int PicoGetModelTotalVertexes( picoModel_t *model ){
+       int i, count;
+
+
+       if ( model == NULL ) {
                return 0;
-       if( model->surface == NULL )
+       }
+       if ( model->surface == NULL ) {
                return 0;
-       
+       }
+
        count = 0;
-       for( i = 0; i < model->numSurfaces; i++ )
-                count += PicoGetSurfaceNumVertexes( model->surface[ i ] );
-       
+       for ( i = 0; i < model->numSurfaces; i++ )
+               count += PicoGetSurfaceNumVertexes( model->surface[ i ] );
+
        return count;
 }
 
 
 
-int PicoGetModelTotalIndexes( picoModel_t *model )
-{
-       int             i, count;
-       
-       
-       if( model == NULL )
+int PicoGetModelTotalIndexes( picoModel_t *model ){
+       int i, count;
+
+
+       if ( model == NULL ) {
                return 0;
-       if( model->surface == NULL )
+       }
+       if ( model->surface == NULL ) {
                return 0;
-       
+       }
+
        count = 0;
-       for( i = 0; i < model->numSurfaces; i++ )
-                count += PicoGetSurfaceNumIndexes( model->surface[ i ] );
-       
+       for ( i = 0; i < model->numSurfaces; i++ )
+               count += PicoGetSurfaceNumIndexes( model->surface[ i ] );
+
        return count;
 }
 
 
 
-char *PicoGetShaderName( picoShader_t *shader )
-{
-       if( shader == NULL )
+char *PicoGetShaderName( picoShader_t *shader ){
+       if ( shader == NULL ) {
                return NULL;
-       if( shader->name == NULL)
+       }
+       if ( shader->name == NULL ) {
                return (char*) "";
+       }
        return shader->name;
 }
 
 
 
-char *PicoGetShaderMapName( picoShader_t *shader )
-{
-       if( shader == NULL )
+char *PicoGetShaderMapName( picoShader_t *shader ){
+       if ( shader == NULL ) {
                return NULL;
-       if( shader->mapName == NULL)
+       }
+       if ( shader->mapName == NULL ) {
                return (char*) "";
+       }
        return shader->mapName;
 }
 
 
 
-picoByte_t *PicoGetShaderAmbientColor( picoShader_t *shader )
-{
-       if( shader == NULL )
+picoByte_t *PicoGetShaderAmbientColor( picoShader_t *shader ){
+       if ( shader == NULL ) {
                return NULL;
+       }
        return shader->ambientColor;
 }
 
 
 
-picoByte_t *PicoGetShaderDiffuseColor( picoShader_t *shader )
-{
-       if( shader == NULL )
+picoByte_t *PicoGetShaderDiffuseColor( picoShader_t *shader ){
+       if ( shader == NULL ) {
                return NULL;
+       }
        return shader->diffuseColor;
 }
 
 
 
-picoByte_t *PicoGetShaderSpecularColor( picoShader_t *shader )
-{
-       if( shader == NULL )
+picoByte_t *PicoGetShaderSpecularColor( picoShader_t *shader ){
+       if ( shader == NULL ) {
                return NULL;
+       }
        return shader->specularColor;
 }
 
 
 
-float PicoGetShaderTransparency( picoShader_t *shader )
-{
-       if( shader == NULL )
+float PicoGetShaderTransparency( picoShader_t *shader ){
+       if ( shader == NULL ) {
                return 0.0f;
+       }
        return shader->transparency;
 }
 
 
 
-float PicoGetShaderShininess( picoShader_t *shader )
-{
-       if( shader == NULL )
+float PicoGetShaderShininess( picoShader_t *shader ){
+       if ( shader == NULL ) {
                return 0.0f;
+       }
        return shader->shininess;
 }
 
 
 
-void *PicoGetSurfaceData( picoSurface_t *surface )
-{
-       if( surface == NULL )
+void *PicoGetSurfaceData( picoSurface_t *surface ){
+       if ( surface == NULL ) {
                return NULL;
+       }
        return surface->data;
 }
 
 
 
-picoSurfaceType_t PicoGetSurfaceType( picoSurface_t *surface )
-{
-       if( surface == NULL )
+picoSurfaceType_t PicoGetSurfaceType( picoSurface_t *surface ){
+       if ( surface == NULL ) {
                return PICO_BAD;
+       }
        return surface->type;
 }
 
 
 
-char *PicoGetSurfaceName( picoSurface_t *surface )
-{
-       if( surface == NULL )
+char *PicoGetSurfaceName( picoSurface_t *surface ){
+       if ( surface == NULL ) {
                return NULL;
-       if( surface->name == NULL )
+       }
+       if ( surface->name == NULL ) {
                return (char*) "";
+       }
        return surface->name;
 }
 
 
 
-picoShader_t *PicoGetSurfaceShader( picoSurface_t *surface )
-{
-       if( surface == NULL )
+picoShader_t *PicoGetSurfaceShader( picoSurface_t *surface ){
+       if ( surface == NULL ) {
                return NULL;
+       }
        return surface->shader;
 }
 
 
 
-int PicoGetSurfaceNumVertexes( picoSurface_t *surface )
-{
-       if( surface == NULL )
+int PicoGetSurfaceNumVertexes( picoSurface_t *surface ){
+       if ( surface == NULL ) {
                return 0;
+       }
        return surface->numVertexes;
 }
 
 
 
-picoVec_t *PicoGetSurfaceXYZ( picoSurface_t *surface, int num )
-{
-       if( surface == NULL || num < 0 || num > surface->numVertexes )
+picoVec_t *PicoGetSurfaceXYZ( picoSurface_t *surface, int num ){
+       if ( surface == NULL || num < 0 || num > surface->numVertexes ) {
                return NULL;
+       }
        return surface->xyz[ num ];
 }
 
 
 
-picoVec_t *PicoGetSurfaceNormal( picoSurface_t *surface, int num )
-{
-       if( surface == NULL || num < 0 || num > surface->numVertexes )
+picoVec_t *PicoGetSurfaceNormal( picoSurface_t *surface, int num ){
+       if ( surface == NULL || num < 0 || num > surface->numVertexes ) {
                return NULL;
+       }
        return surface->normal[ num ];
 }
 
 
 
-picoVec_t *PicoGetSurfaceST( picoSurface_t *surface, int array, int num  )
-{
-       if( surface == NULL || array < 0 || array > surface->numSTArrays || num < 0 || num > surface->numVertexes )
+picoVec_t *PicoGetSurfaceST( picoSurface_t *surface, int array, int num  ){
+       if ( surface == NULL || array < 0 || array > surface->numSTArrays || num < 0 || num > surface->numVertexes ) {
                return NULL;
+       }
        return surface->st[ array ][ num ];
 }
 
 
 
-picoByte_t *PicoGetSurfaceColor( picoSurface_t *surface, int array, int num )
-{
-       if( surface == NULL || array < 0 || array > surface->numColorArrays || num < 0 || num > surface->numVertexes )
+picoByte_t *PicoGetSurfaceColor( picoSurface_t *surface, int array, int num ){
+       if ( surface == NULL || array < 0 || array > surface->numColorArrays || num < 0 || num > surface->numVertexes ) {
                return NULL;
+       }
        return surface->color[ array ][ num ];
 }
 
 
 
-int PicoGetSurfaceNumIndexes( picoSurface_t *surface )
-{
-       if( surface == NULL )
+int PicoGetSurfaceNumIndexes( picoSurface_t *surface ){
+       if ( surface == NULL ) {
                return 0;
+       }
        return surface->numIndexes;
 }
 
 
 
-picoIndex_t PicoGetSurfaceIndex( picoSurface_t *surface, int num )
-{
-       if( surface == NULL || num < 0 || num > surface->numIndexes )
+picoIndex_t PicoGetSurfaceIndex( picoSurface_t *surface, int num ){
+       if ( surface == NULL || num < 0 || num > surface->numIndexes ) {
                return 0;
+       }
        return surface->index[ num ];
 }
 
 
 
-picoIndex_t *PicoGetSurfaceIndexes( picoSurface_t *surface, int num )
-{
-       if( surface == NULL || num < 0 || num > surface->numIndexes )
+picoIndex_t *PicoGetSurfaceIndexes( picoSurface_t *surface, int num ){
+       if ( surface == NULL || num < 0 || num > surface->numIndexes ) {
                return NULL;
+       }
        return &surface->index[ num ];
 }
 
 
-picoVec_t *PicoGetFaceNormal( picoSurface_t *surface, int num )
-{
-       if( surface == NULL || num < 0 || num > surface->numFaceNormals )
+picoVec_t *PicoGetFaceNormal( picoSurface_t *surface, int num ){
+       if ( surface == NULL || num < 0 || num > surface->numFaceNormals ) {
                return NULL;
+       }
        return surface->faceNormal[ num ];
 }
 
+picoIndex_t PicoGetSurfaceSmoothingGroup( picoSurface_t *surface, int num ){
+       if ( surface == NULL || num < 0 || num > surface->numVertexes ) {
+               return -1;
+       }
+       return surface->smoothingGroup[ num ];
+}
 
-int PicoGetSurfaceSpecial( picoSurface_t *surface, int num )
-{
-       if( surface == NULL || num < 0 || num >= PICO_MAX_SPECIAL )
+
+int PicoGetSurfaceSpecial( picoSurface_t *surface, int num ){
+       if ( surface == NULL || num < 0 || num >= PICO_MAX_SPECIAL ) {
                return 0;
+       }
        return surface->special[ num ];
 }
 
 
 
 /* ----------------------------------------------------------------------------
-hashtable related functions
----------------------------------------------------------------------------- */
+   hashtable related functions
+   ---------------------------------------------------------------------------- */
 
 /* hashtable code for faster vertex lookups */
 //#define HASHTABLE_SIZE 32768 // 2048                 /* power of 2, use & */
-#define HASHTABLE_SIZE 7919 // 32749 // 2039   /* prime, use % */
+#define HASHTABLE_SIZE 7919 // 32749 // 2039    /* prime, use % */
 
-int PicoGetHashTableSize( void )
-{
+int PicoGetHashTableSize( void ){
        return HASHTABLE_SIZE;
 }
 
 #define HASH_USE_EPSILON
 
 #ifdef HASH_USE_EPSILON
-#define HASH_XYZ_EPSILON                                       0.01f
-#define HASH_XYZ_EPSILONSPACE_MULTIPLIER       1.f / HASH_XYZ_EPSILON
-#define HASH_ST_EPSILON                                                0.0001f
-#define HASH_NORMAL_EPSILON                                    0.02f
+#define HASH_XYZ_EPSILON                    0.01f
+#define HASH_XYZ_EPSILONSPACE_MULTIPLIER    1.f / HASH_XYZ_EPSILON
+#define HASH_ST_EPSILON                     0.0001f
+#define HASH_NORMAL_EPSILON                 0.02f
 #endif
 
-unsigned int PicoVertexCoordGenerateHash( picoVec3_t xyz )
-{
+unsigned int PicoVertexCoordGenerateHash( picoVec3_t xyz ){
        unsigned int hash = 0;
 
 #ifndef HASH_USE_EPSILON
-       hash += ~(*((unsigned int*) &xyz[ 0 ]) << 15);
-       hash ^= (*((unsigned int*) &xyz[ 0 ]) >> 10);
-       hash += (*((unsigned int*) &xyz[ 1 ]) << 3);
-       hash ^= (*((unsigned int*) &xyz[ 1 ]) >> 6);
-       hash += ~(*((unsigned int*) &xyz[ 2 ]) << 11);
-       hash ^= (*((unsigned int*) &xyz[ 2 ]) >> 16);
+       hash += ~( *( (unsigned int*) &xyz[ 0 ] ) << 15 );
+       hash ^= ( *( (unsigned int*) &xyz[ 0 ] ) >> 10 );
+       hash += ( *( (unsigned int*) &xyz[ 1 ] ) << 3 );
+       hash ^= ( *( (unsigned int*) &xyz[ 1 ] ) >> 6 );
+       hash += ~( *( (unsigned int*) &xyz[ 2 ] ) << 11 );
+       hash ^= ( *( (unsigned int*) &xyz[ 2 ] ) >> 16 );
 #else
        picoVec3_t xyz_epsilonspace;
 
        _pico_scale_vec( xyz, HASH_XYZ_EPSILONSPACE_MULTIPLIER, xyz_epsilonspace );
-       xyz_epsilonspace[ 0 ] = (float)floor(xyz_epsilonspace[ 0 ]);
-       xyz_epsilonspace[ 1 ] = (float)floor(xyz_epsilonspace[ 1 ]);
-       xyz_epsilonspace[ 2 ] = (float)floor(xyz_epsilonspace[ 2 ]);
-
-       hash += ~(*((unsigned int*) &xyz_epsilonspace[ 0 ]) << 15);
-       hash ^= (*((unsigned int*) &xyz_epsilonspace[ 0 ]) >> 10);
-       hash += (*((unsigned int*) &xyz_epsilonspace[ 1 ]) << 3);
-       hash ^= (*((unsigned int*) &xyz_epsilonspace[ 1 ]) >> 6);
-       hash += ~(*((unsigned int*) &xyz_epsilonspace[ 2 ]) << 11);
-       hash ^= (*((unsigned int*) &xyz_epsilonspace[ 2 ]) >> 16);
+       xyz_epsilonspace[ 0 ] = (float)floor( xyz_epsilonspace[ 0 ] );
+       xyz_epsilonspace[ 1 ] = (float)floor( xyz_epsilonspace[ 1 ] );
+       xyz_epsilonspace[ 2 ] = (float)floor( xyz_epsilonspace[ 2 ] );
+
+       hash += ~( *( (unsigned int*) &xyz_epsilonspace[ 0 ] ) << 15 );
+       hash ^= ( *( (unsigned int*) &xyz_epsilonspace[ 0 ] ) >> 10 );
+       hash += ( *( (unsigned int*) &xyz_epsilonspace[ 1 ] ) << 3 );
+       hash ^= ( *( (unsigned int*) &xyz_epsilonspace[ 1 ] ) >> 6 );
+       hash += ~( *( (unsigned int*) &xyz_epsilonspace[ 2 ] ) << 11 );
+       hash ^= ( *( (unsigned int*) &xyz_epsilonspace[ 2 ] ) >> 16 );
 #endif
 
        //hash = hash & (HASHTABLE_SIZE-1);
-       hash = hash % (HASHTABLE_SIZE);
+       hash = hash % ( HASHTABLE_SIZE );
        return hash;
 }
 
-picoVertexCombinationHash_t **PicoNewVertexCombinationHashTable( void )
-{
-       picoVertexCombinationHash_t     **hashTable = _pico_alloc( HASHTABLE_SIZE * sizeof(picoVertexCombinationHash_t*) );
+picoVertexCombinationHash_t **PicoNewVertexCombinationHashTable( void ){
+       picoVertexCombinationHash_t **hashTable = _pico_alloc( HASHTABLE_SIZE * sizeof( picoVertexCombinationHash_t* ) );
 
-       memset( hashTable, 0, HASHTABLE_SIZE * sizeof(picoVertexCombinationHash_t*) );
+       memset( hashTable, 0, HASHTABLE_SIZE * sizeof( picoVertexCombinationHash_t* ) );
 
        return hashTable;
 }
 
-void PicoFreeVertexCombinationHashTable( picoVertexCombinationHash_t **hashTable )
-{
-       int                                                     i;
-       picoVertexCombinationHash_t     *vertexCombinationHash;
+void PicoFreeVertexCombinationHashTable( picoVertexCombinationHash_t **hashTable ){
+       int i;
+       picoVertexCombinationHash_t *vertexCombinationHash;
        picoVertexCombinationHash_t *nextVertexCombinationHash;
 
        /* dummy check */
-       if (hashTable == NULL)
+       if ( hashTable == NULL ) {
                return;
+       }
 
-       for( i = 0; i < HASHTABLE_SIZE; i++ )
+       for ( i = 0; i < HASHTABLE_SIZE; i++ )
        {
-               if (hashTable[ i ])
-               {
+               if ( hashTable[ i ] ) {
                        nextVertexCombinationHash = NULL;
 
-                       for( vertexCombinationHash = hashTable[ i ]; vertexCombinationHash; vertexCombinationHash = nextVertexCombinationHash )
+                       for ( vertexCombinationHash = hashTable[ i ]; vertexCombinationHash; vertexCombinationHash = nextVertexCombinationHash )
                        {
                                nextVertexCombinationHash = vertexCombinationHash->next;
-                               if (vertexCombinationHash->data != NULL)
-                               {
+                               if ( vertexCombinationHash->data != NULL ) {
                                        _pico_free( vertexCombinationHash->data );
                                }
                                _pico_free( vertexCombinationHash );
@@ -1392,53 +1509,60 @@ void PicoFreeVertexCombinationHashTable( picoVertexCombinationHash_t **hashTable
        _pico_free( hashTable );
 }
 
-picoVertexCombinationHash_t *PicoFindVertexCombinationInHashTable( picoVertexCombinationHash_t **hashTable, picoVec3_t xyz, picoVec3_t normal, picoVec3_t st, picoColor_t color )
-{
-       unsigned int                            hash;
-       picoVertexCombinationHash_t     *vertexCombinationHash;
+picoVertexCombinationHash_t *PicoFindVertexCombinationInHashTable( picoVertexCombinationHash_t **hashTable, picoVec3_t xyz, picoVec3_t normal, picoVec3_t st, picoColor_t color ){
+       unsigned int hash;
+       picoVertexCombinationHash_t *vertexCombinationHash;
 
        /* dumy check */
-       if (hashTable == NULL || xyz == NULL || normal == NULL || st == NULL || color == NULL )
+       if ( hashTable == NULL || xyz == NULL || normal == NULL || st == NULL || color == NULL ) {
                return NULL;
+       }
 
        hash = PicoVertexCoordGenerateHash( xyz );
 
-       for( vertexCombinationHash = hashTable[ hash ]; vertexCombinationHash; vertexCombinationHash = vertexCombinationHash->next )
+       for ( vertexCombinationHash = hashTable[ hash ]; vertexCombinationHash; vertexCombinationHash = vertexCombinationHash->next )
        {
 #ifndef HASH_USE_EPSILON
                /* check xyz */
-               if( (vertexCombinationHash->vcd.xyz[ 0 ] != xyz[ 0 ] || vertexCombinationHash->vcd.xyz[ 1 ] != xyz[ 1 ] || vertexCombinationHash->vcd.xyz[ 2 ] != xyz[ 2 ]) )
+               if ( ( vertexCombinationHash->vcd.xyz[ 0 ] != xyz[ 0 ] || vertexCombinationHash->vcd.xyz[ 1 ] != xyz[ 1 ] || vertexCombinationHash->vcd.xyz[ 2 ] != xyz[ 2 ] ) ) {
                        continue;
+               }
 
                /* check normal */
-               if( (vertexCombinationHash->vcd.normal[ 0 ] != normal[ 0 ] || vertexCombinationHash->vcd.normal[ 1 ] != normal[ 1 ] || vertexCombinationHash->vcd.normal[ 2 ] != normal[ 2 ]) )
+               if ( ( vertexCombinationHash->vcd.normal[ 0 ] != normal[ 0 ] || vertexCombinationHash->vcd.normal[ 1 ] != normal[ 1 ] || vertexCombinationHash->vcd.normal[ 2 ] != normal[ 2 ] ) ) {
                        continue;
-               
+               }
+
                /* check st */
-               if( vertexCombinationHash->vcd.st[ 0 ] != st[ 0 ] || vertexCombinationHash->vcd.st[ 1 ] != st[ 1 ] )
+               if ( vertexCombinationHash->vcd.st[ 0 ] != st[ 0 ] || vertexCombinationHash->vcd.st[ 1 ] != st[ 1 ] ) {
                        continue;
+               }
 #else
                /* check xyz */
-               if( ( fabs(xyz[ 0 ] - vertexCombinationHash->vcd.xyz[ 0 ]) ) > HASH_XYZ_EPSILON ||
-                       ( fabs(xyz[ 1 ] - vertexCombinationHash->vcd.xyz[ 1 ]) ) > HASH_XYZ_EPSILON ||
-                       ( fabs(xyz[ 2 ] - vertexCombinationHash->vcd.xyz[ 2 ]) ) > HASH_XYZ_EPSILON )
+               if ( ( fabs( xyz[ 0 ] - vertexCombinationHash->vcd.xyz[ 0 ] ) ) > HASH_XYZ_EPSILON ||
+                        ( fabs( xyz[ 1 ] - vertexCombinationHash->vcd.xyz[ 1 ] ) ) > HASH_XYZ_EPSILON ||
+                        ( fabs( xyz[ 2 ] - vertexCombinationHash->vcd.xyz[ 2 ] ) ) > HASH_XYZ_EPSILON ) {
                        continue;
+               }
 
                /* check normal */
-               if( ( fabs(normal[ 0 ] - vertexCombinationHash->vcd.normal[ 0 ]) ) > HASH_NORMAL_EPSILON ||
-                       ( fabs(normal[ 1 ] - vertexCombinationHash->vcd.normal[ 1 ]) ) > HASH_NORMAL_EPSILON ||
-                       ( fabs(normal[ 2 ] - vertexCombinationHash->vcd.normal[ 2 ]) ) > HASH_NORMAL_EPSILON )
+               if ( ( fabs( normal[ 0 ] - vertexCombinationHash->vcd.normal[ 0 ] ) ) > HASH_NORMAL_EPSILON ||
+                        ( fabs( normal[ 1 ] - vertexCombinationHash->vcd.normal[ 1 ] ) ) > HASH_NORMAL_EPSILON ||
+                        ( fabs( normal[ 2 ] - vertexCombinationHash->vcd.normal[ 2 ] ) ) > HASH_NORMAL_EPSILON ) {
                        continue;
-               
+               }
+
                /* check st */
-               if( ( fabs(st[ 0 ] - vertexCombinationHash->vcd.st[ 0 ]) ) > HASH_ST_EPSILON ||
-                       ( fabs(st[ 1 ] - vertexCombinationHash->vcd.st[ 1 ]) ) > HASH_ST_EPSILON )
+               if ( ( fabs( st[ 0 ] - vertexCombinationHash->vcd.st[ 0 ] ) ) > HASH_ST_EPSILON ||
+                        ( fabs( st[ 1 ] - vertexCombinationHash->vcd.st[ 1 ] ) ) > HASH_ST_EPSILON ) {
                        continue;
+               }
 #endif
 
                /* check color */
-               if( *((int*) vertexCombinationHash->vcd.color) != *((int*) color) )
+               if ( *( (int*) vertexCombinationHash->vcd.color ) != *( (int*) color ) ) {
                        continue;
+               }
 
                /* gotcha */
                return vertexCombinationHash;
@@ -1447,19 +1571,20 @@ picoVertexCombinationHash_t *PicoFindVertexCombinationInHashTable( picoVertexCom
        return NULL;
 }
 
-picoVertexCombinationHash_t *PicoAddVertexCombinationToHashTable( picoVertexCombinationHash_t **hashTable, picoVec3_t xyz, picoVec3_t normal, picoVec3_t st, picoColor_t color, picoIndex_t index )
-{
-       unsigned int                            hash;
-       picoVertexCombinationHash_t     *vertexCombinationHash;
+picoVertexCombinationHash_t *PicoAddVertexCombinationToHashTable( picoVertexCombinationHash_t **hashTable, picoVec3_t xyz, picoVec3_t normal, picoVec3_t st, picoColor_t color, picoIndex_t index ){
+       unsigned int hash;
+       picoVertexCombinationHash_t *vertexCombinationHash;
 
        /* dumy check */
-       if (hashTable == NULL || xyz == NULL || normal == NULL || st == NULL || color == NULL )
+       if ( hashTable == NULL || xyz == NULL || normal == NULL || st == NULL || color == NULL ) {
                return NULL;
+       }
 
-       vertexCombinationHash = _pico_alloc( sizeof(picoVertexCombinationHash_t) );
+       vertexCombinationHash = _pico_alloc( sizeof( picoVertexCombinationHash_t ) );
 
-       if (!vertexCombinationHash)
+       if ( !vertexCombinationHash ) {
                return NULL;
+       }
 
        hash = PicoVertexCoordGenerateHash( xyz );
 
@@ -1476,299 +1601,488 @@ picoVertexCombinationHash_t *PicoAddVertexCombinationToHashTable( picoVertexComb
 }
 
 /* ----------------------------------------------------------------------------
-specialized routines
----------------------------------------------------------------------------- */
+   specialized routines
+   ---------------------------------------------------------------------------- */
 
 /*
-PicoFindSurfaceVertex()
-finds a vertex matching the set parameters
-fixme: needs non-naive algorithm
-*/
+   PicoFindSurfaceVertex()
+   finds a vertex matching the set parameters
+   fixme: needs non-naive algorithm
+ */
+
+int PicoFindSurfaceVertexNum( picoSurface_t *surface, picoVec3_t xyz, picoVec3_t normal, int numSTs, picoVec2_t *st, int numColors, picoColor_t *color, picoIndex_t smoothingGroup ){
+       int i, j;
+
 
-int PicoFindSurfaceVertexNum( picoSurface_t *surface, picoVec3_t xyz, picoVec3_t normal, int numSTs, picoVec2_t *st, int numColors, picoColor_t *color )
-{
-       int             i, j;
-       
-       
        /* dummy check */
-       if( surface == NULL || surface->numVertexes <= 0 )
+       if ( surface == NULL || surface->numVertexes <= 0 ) {
                return -1;
-       
+       }
+
        /* walk vertex list */
-       for( i = 0; i < surface->numVertexes; i++ )
+       for ( i = 0; i < surface->numVertexes; i++ )
        {
                /* check xyz */
-               if( xyz != NULL && (surface->xyz[ i ][ 0 ] != xyz[ 0 ] || surface->xyz[ i ][ 1 ] != xyz[ 1 ] || surface->xyz[ i ][ 2 ] != xyz[ 2 ]) )
+               if ( xyz != NULL && ( surface->xyz[ i ][ 0 ] != xyz[ 0 ] || surface->xyz[ i ][ 1 ] != xyz[ 1 ] || surface->xyz[ i ][ 2 ] != xyz[ 2 ] ) ) {
+                       continue;
+               }
+
+               /* check normal */
+               if ( normal != NULL && ( surface->normal[ i ][ 0 ] != normal[ 0 ] || surface->normal[ i ][ 1 ] != normal[ 1 ] || surface->normal[ i ][ 2 ] != normal[ 2 ] ) ) {
                        continue;
-               
+               }
+
                /* check normal */
-               if( normal != NULL && (surface->normal[ i ][ 0 ] != normal[ 0 ] || surface->normal[ i ][ 1 ] != normal[ 1 ] || surface->normal[ i ][ 2 ] != normal[ 2 ]) )
+               if ( surface->smoothingGroup[ i ] != smoothingGroup ) {
                        continue;
-               
+               }
+
                /* check st */
-               if( numSTs > 0 && st != NULL )
-               {
-                       for( j = 0; j < numSTs; j++ )
+               if ( numSTs > 0 && st != NULL ) {
+                       for ( j = 0; j < numSTs; j++ )
                        {
-                               if( surface->st[ j ][ i ][ 0 ] != st[ j ][ 0 ] || surface->st[ j ][ i ][ 1 ] != st[ j ][ 1 ] )
+                               if ( surface->st[ j ][ i ][ 0 ] != st[ j ][ 0 ] || surface->st[ j ][ i ][ 1 ] != st[ j ][ 1 ] ) {
                                        break;
+                               }
                        }
-                       if( j != numSTs )
+                       if ( j != numSTs ) {
                                continue;
+                       }
                }
-               
+
                /* check color */
-               if( numColors > 0 && color != NULL )
-               {
-                       for( j = 0; j < numSTs; j++ )
+               if ( numColors > 0 && color != NULL ) {
+                       for ( j = 0; j < numSTs; j++ )
                        {
-                               if( *((int*) surface->color[ j ]) != *((int*) color[ j ]) )
+                               if ( *( (int*) surface->color[ j ] ) != *( (int*) color[ j ] ) ) {
                                        break;
+                               }
                        }
-                       if( j != numColors )
+                       if ( j != numColors ) {
                                continue;
+                       }
                }
-               
+
                /* vertex matches */
                return i;
        }
-       
+
        /* nada */
        return -1;
 }
 
 
 
-/*
-PicoFixSurfaceNormals()
-fixes broken normals (certain formats bork normals)
-*/
 
-#define MAX_NORMAL_VOTES               128
-#define EQUAL_NORMAL_EPSILON   0.01
-#define BAD_NORMAL_EPSILON             0.5
+typedef struct _IndexArray IndexArray;
+struct _IndexArray
+{
+       picoIndex_t* data;
+       picoIndex_t* last;
+};
+
+void indexarray_push_back( IndexArray* self, picoIndex_t value ){
+       *self->last++ = value;
+}
 
-void PicoFixSurfaceNormals( picoSurface_t *surface )
+size_t indexarray_size( IndexArray* self ){
+       return self->last - self->data;
+}
+
+void indexarray_reserve( IndexArray* self, size_t size ){
+       self->data = self->last = _pico_calloc( size, sizeof( picoIndex_t ) );
+}
+
+void indexarray_clear( IndexArray* self ){
+       _pico_free( self->data );
+}
+
+typedef struct _BinaryTreeNode BinaryTreeNode;
+struct _BinaryTreeNode
 {
-       int                             i, j, k, a, b, c, numVotes, faceIndex;
-       picoVec3_t              votes[ MAX_NORMAL_VOTES ];
-       picoVec3_t              *normals, diff;
-       picoVec4_t              plane;
-       
-       
-       /* dummy check */
-       if( surface == NULL || surface->numVertexes == 0 )
-               return;
-       
-       /* fixme: handle other surface types */
-       if( surface->type != PICO_TRIANGLES )
-               return;
-       
-       /* allocate normal storage */
-       normals = _pico_alloc( surface->numVertexes * sizeof( *normals ) );
-       if( normals == NULL )
-       {
-               _pico_printf( PICO_ERROR, "PicoFixSurfaceNormals: Unable to allocate memory for temporary normal storage" );
-               return;
-       }
-       
-       /* zero it out */
-       memset( normals, 0, surface->numVertexes * sizeof( *normals ) );
-       
-       /* walk vertex list */
-       for( i = 0; i < surface->numVertexes; i++ )
+       picoIndex_t left;
+       picoIndex_t right;
+};
+
+typedef struct _BinaryTree BinaryTree;
+struct _BinaryTree
+{
+       BinaryTreeNode* data;
+       BinaryTreeNode* last;
+};
+
+void binarytree_extend( BinaryTree* self ){
+       self->last->left = 0;
+       self->last->right = 0;
+       ++self->last;
+}
+
+size_t binarytree_size( BinaryTree* self ){
+       return self->last - self->data;
+}
+
+void binarytree_reserve( BinaryTree* self, size_t size ){
+       self->data = self->last = _pico_calloc( size, sizeof( BinaryTreeNode ) );
+}
+
+void binarytree_clear( BinaryTree* self ){
+       _pico_free( self->data );
+}
+
+typedef int ( *LessFunc )( void*, picoIndex_t, picoIndex_t );
+
+typedef struct _UniqueIndices UniqueIndices;
+struct _UniqueIndices
+{
+       BinaryTree tree;
+       IndexArray indices;
+       LessFunc lessFunc;
+       void* lessData;
+};
+
+size_t UniqueIndices_size( UniqueIndices* self ){
+       return binarytree_size( &self->tree );
+}
+
+void UniqueIndices_reserve( UniqueIndices* self, size_t size ){
+       binarytree_reserve( &self->tree, size );
+       indexarray_reserve( &self->indices, size );
+}
+
+void UniqueIndices_init( UniqueIndices* self, LessFunc lessFunc, void* lessData ){
+       self->lessFunc = lessFunc;
+       self->lessData = lessData;
+}
+
+void UniqueIndices_destroy( UniqueIndices* self ){
+       binarytree_clear( &self->tree );
+       indexarray_clear( &self->indices );
+}
+
+
+picoIndex_t UniqueIndices_find_or_insert( UniqueIndices* self, picoIndex_t value ){
+       picoIndex_t index = 0;
+
+       for (;; )
        {
-               /* zero out votes */
-               numVotes = 0;
-               
-               /* find all the triangles that reference this vertex */
-               for( j = 0, faceIndex = 0; j < surface->numIndexes; j += 3, faceIndex++ )
-               {
-                       /* get triangle */
-                       a = surface->index[ j ];
-                       b = surface->index[ j + 1 ];
-                       c = surface->index[ j + 2 ];
-                       
-                       /* ignore degenerate triangles */
-                       if( a == b || b == c || c == a )
+               if ( self->lessFunc( self->lessData, value, self->indices.data[index] ) ) {
+                       BinaryTreeNode* node = self->tree.data + index;
+                       if ( node->left != 0 ) {
+                               index = node->left;
                                continue;
-                       
-                       /* ignore indexes out of range */
-                       if( a < 0 || a >= surface->numVertexes ||
-                               b < 0 || b >= surface->numVertexes ||
-                               c < 0 || c >= surface->numVertexes )
+                       }
+                       else
+                       {
+                               node->left = (picoIndex_t)binarytree_size( &self->tree );
+                               binarytree_extend( &self->tree );
+                               indexarray_push_back( &self->indices, value );
+                               return node->left;
+                       }
+               }
+               if ( self->lessFunc( self->lessData, self->indices.data[index], value ) ) {
+                       BinaryTreeNode* node = self->tree.data + index;
+                       if ( node->right != 0 ) {
+                               index = node->right;
                                continue;
-                       
-                       /* test triangle */
-                       if( a == i || b == i || c == i )
+                       }
+                       else
                        {
-                               /* if this surface has face normals */
-                               if( surface->numFaceNormals && faceIndex < surface->numFaceNormals )
-                               {
-                                       _pico_copy_vec( surface->faceNormal[ faceIndex ], plane );
-                                       if( plane[ 0 ] == 0.f && plane[ 1 ] == 0.f && plane[ 2 ] == 0.f )
-                                       {
-                                               /* if null normal, make plane from the 3 points */
-                                               if( _pico_calc_plane( plane, surface->xyz[ a ], surface->xyz[ b ], surface->xyz[ c ] ) == 0 )
-                                               {
-                                                       continue;
-                                               }
-                                       }
-                               }
-                               /* make a plane from the 3 points */
-                               else if( _pico_calc_plane( plane, surface->xyz[ a ], surface->xyz[ b ], surface->xyz[ c ] ) == 0 )
-                               {
-                                       continue;
-                               }
+                               node->right = (picoIndex_t)binarytree_size( &self->tree );
+                               binarytree_extend( &self->tree );
+                               indexarray_push_back( &self->indices, value );
+                               return node->right;
+                       }
+               }
 
-                               /* see if this normal has already been voted */
-                               for( k = 0; k < numVotes; k++ )
-                               {
-                                       _pico_subtract_vec( plane, votes[ k ], diff );
-                                       if( fabs( diff[ 0 ] ) < EQUAL_NORMAL_EPSILON &&
-                                               fabs( diff[ 1 ] ) < EQUAL_NORMAL_EPSILON &&
-                                               fabs( diff[ 2 ] ) < EQUAL_NORMAL_EPSILON )
-                                               break;
-                               }
-                               
-                               /* add a new vote? */
-                               if( k == numVotes && numVotes < MAX_NORMAL_VOTES )
-                               {
-                                       _pico_copy_vec( plane, votes[ numVotes ] );
-                                       numVotes++;
-                               }
+               return index;
+       }
+}
+
+picoIndex_t UniqueIndices_insert( UniqueIndices* self, picoIndex_t value ){
+       if ( self->tree.data == self->tree.last ) {
+               binarytree_extend( &self->tree );
+               indexarray_push_back( &self->indices, value );
+               return 0;
+       }
+       else
+       {
+               return UniqueIndices_find_or_insert( self, value );
+       }
+}
+
+typedef struct picoSmoothVertices_s picoSmoothVertices_t;
+struct picoSmoothVertices_s
+{
+       picoVec3_t* xyz;
+       picoIndex_t* smoothingGroups;
+};
+
+int lessSmoothVertex( void* data, picoIndex_t first, picoIndex_t second ){
+       picoSmoothVertices_t* smoothVertices = data;
+
+       if ( smoothVertices->xyz[first][0] != smoothVertices->xyz[second][0] ) {
+               return smoothVertices->xyz[first][0] < smoothVertices->xyz[second][0];
+       }
+       if ( smoothVertices->xyz[first][1] != smoothVertices->xyz[second][1] ) {
+               return smoothVertices->xyz[first][1] < smoothVertices->xyz[second][1];
+       }
+       if ( smoothVertices->xyz[first][2] != smoothVertices->xyz[second][2] ) {
+               return smoothVertices->xyz[first][2] < smoothVertices->xyz[second][2];
+       }
+       if ( smoothVertices->smoothingGroups[first] != smoothVertices->smoothingGroups[second] ) {
+               return smoothVertices->smoothingGroups[first] < smoothVertices->smoothingGroups[second];
+       }
+       return 0;
+}
+
+void _pico_vertices_combine_shared_normals( picoVec3_t* xyz, picoIndex_t* smoothingGroups, picoVec3_t* normals, picoIndex_t numVertices ){
+       UniqueIndices vertices;
+       IndexArray indices;
+       picoSmoothVertices_t smoothVertices = { xyz, smoothingGroups };
+       UniqueIndices_init( &vertices, lessSmoothVertex, &smoothVertices );
+       UniqueIndices_reserve( &vertices, numVertices );
+       indexarray_reserve( &indices, numVertices );
+
+
+       {
+               picoIndex_t i = 0;
+               for (; i < numVertices; ++i )
+               {
+                       size_t size = UniqueIndices_size( &vertices );
+                       picoIndex_t index = UniqueIndices_insert( &vertices, i );
+                       if ( (size_t)index != size ) {
+                               float* normal = normals[vertices.indices.data[index]];
+                               _pico_add_vec( normal, normals[i], normal );
                        }
+                       indexarray_push_back( &indices, index );
                }
-               
-               /* tally votes */
-               if( numVotes > 0 )
+       }
+
+       {
+               picoIndex_t maxIndex = 0;
+               picoIndex_t* i = indices.data;
+               for (; i != indices.last; ++i )
                {
-                       /* create average normal */
-                       _pico_zero_vec( normals[ i ] );
-                       for( k = 0; k < numVotes; k++ )
-                               _pico_add_vec( normals[ i ], votes[ k ], normals[ i ] );
-                       
-                       /* normalize it */
-                       if( _pico_normalize_vec( normals[ i ] ) )
+                       if ( *i <= maxIndex ) {
+                               _pico_copy_vec( normals[vertices.indices.data[*i]], normals[i - indices.data] );
+                       }
+                       else
                        {
-                               /* test against actual normal */
-                               if( fabs( _pico_dot_vec( normals[ i ], surface->normal[ i ] ) - 1 ) > BAD_NORMAL_EPSILON )
+                               maxIndex = *i;
+                       }
+               }
+       }
+
+       UniqueIndices_destroy( &vertices );
+       indexarray_clear( &indices );
+}
+
+typedef picoVec3_t* picoNormalIter_t;
+typedef picoIndex_t* picoIndexIter_t;
+
+#define THE_CROSSPRODUCTS_OF_ANY_PAIR_OF_EDGES_OF_A_GIVEN_TRIANGLE_ARE_EQUAL 1
+
+void _pico_triangles_generate_weighted_normals( picoIndexIter_t first, picoIndexIter_t end, picoVec3_t* xyz, picoVec3_t* normals ){
+       for (; first != end; first += 3 )
+       {
+#if ( THE_CROSSPRODUCTS_OF_ANY_PAIR_OF_EDGES_OF_A_GIVEN_TRIANGLE_ARE_EQUAL )
+               picoVec3_t weightedNormal;
+               {
+                       float* a = xyz[*( first + 0 )];
+                       float* b = xyz[*( first + 1 )];
+                       float* c = xyz[*( first + 2 )];
+                       picoVec3_t ba, ca;
+                       _pico_subtract_vec( b, a, ba );
+                       _pico_subtract_vec( c, a, ca );
+                       _pico_cross_vec( ca, ba, weightedNormal );
+               }
+#endif
+               {
+                       int j = 0;
+                       for (; j < 3; ++j )
+                       {
+                               float* normal = normals[*( first + j )];
+#if ( !THE_CROSSPRODUCTS_OF_ANY_PAIR_OF_EDGES_OF_A_GIVEN_TRIANGLE_ARE_EQUAL )
+                               picoVec3_t weightedNormal;
                                {
-                                       //%     printf( "Normal %8d: (%f %f %f) -> (%f %f %f)\n", i,
-                                       //%             surface->normal[ i ][ 0 ], surface->normal[ i ][ 1 ], surface->normal[ i ][ 2 ],
-                                       //%             normals[ i ][ 0 ], normals[ i ][ 1 ], normals[ i ][ 2 ] );
-                                       _pico_copy_vec( normals[ i ], surface->normal[ i ] );
+                                       float* a = xyz[*( first + ( ( j + 0 ) % 3 ) )];
+                                       float* b = xyz[*( first + ( ( j + 1 ) % 3 ) )];
+                                       float* c = xyz[*( first + ( ( j + 2 ) % 3 ) )];
+                                       picoVec3_t ba, ca;
+                                       _pico_subtract_vec( b, a, ba );
+                                       _pico_subtract_vec( c, a, ca );
+                                       _pico_cross_vec( ca, ba, weightedNormal );
                                }
+#endif
+                               _pico_add_vec( weightedNormal, normal, normal );
                        }
                }
        }
-       
-       /* free normal storage */
-       _pico_free( normals );
 }
 
+void _pico_normals_zero( picoNormalIter_t first, picoNormalIter_t last ){
+       for (; first != last; ++first )
+       {
+               _pico_zero_vec( *first );
+       }
+}
+
+void _pico_normals_normalize( picoNormalIter_t first, picoNormalIter_t last ){
+       for (; first != last; ++first )
+       {
+               _pico_normalize_vec( *first );
+       }
+}
+
+double _pico_length_vec( picoVec3_t vec ){
+       return sqrt( vec[ 0 ] * vec[ 0 ] + vec[ 1 ] * vec[ 1 ] + vec[ 2 ] * vec[ 2 ] );
+}
+
+#define NORMAL_UNIT_LENGTH_EPSILON 0.01
+#define FLOAT_EQUAL_EPSILON( f, other, epsilon ) ( fabs( f - other ) < epsilon )
+
+int _pico_normal_is_unit_length( picoVec3_t normal ){
+       return FLOAT_EQUAL_EPSILON( _pico_length_vec( normal ), 1.0, NORMAL_UNIT_LENGTH_EPSILON );
+}
+
+int _pico_normal_within_tolerance( picoVec3_t normal, picoVec3_t other ){
+       return _pico_dot_vec( normal, other ) > 0.0f;
+}
+
+
+void _pico_normals_assign_generated_normals( picoNormalIter_t first, picoNormalIter_t last, picoNormalIter_t generated ){
+       for (; first != last; ++first, ++generated )
+       {
+               if ( !_pico_normal_is_unit_length( *first ) || !_pico_normal_within_tolerance( *first, *generated ) ) {
+                       _pico_copy_vec( *generated, *first );
+               }
+       }
+}
+
+void PicoFixSurfaceNormals( picoSurface_t* surface ){
+       picoVec3_t* normals = (picoVec3_t*)_pico_calloc( surface->numVertexes, sizeof( picoVec3_t ) );
+
+       _pico_normals_zero( normals, normals + surface->numVertexes );
+
+       _pico_triangles_generate_weighted_normals( surface->index, surface->index + surface->numIndexes, surface->xyz, normals );
+       _pico_vertices_combine_shared_normals( surface->xyz, surface->smoothingGroup, normals, surface->numVertexes );
+
+       _pico_normals_normalize( normals, normals + surface->numVertexes );
+
+       _pico_normals_assign_generated_normals( surface->normal, surface->normal + surface->numVertexes, normals );
 
+       _pico_free( normals );
+}
 
 
 /*
-PicoRemapModel() - sea
-remaps model material/etc. information using the remappings
-contained in the given 'remapFile' (full path to the ascii file to open)
-returns 1 on success or 0 on error
-*/
+   PicoRemapModel() - sea
+   remaps model material/etc. information using the remappings
+   contained in the given 'remapFile' (full path to the ascii file to open)
+   returns 1 on success or 0 on error
+ */
 
 #define _prm_error_return \
-{ \
-       _pico_free_parser( p ); \
-       _pico_free_file( remapBuffer ); \
-       return 0; \
-}
+       { \
+               _pico_free_parser( p ); \
+               _pico_free_file( remapBuffer ); \
+               return 0; \
+       }
+
+int PicoRemapModel( picoModel_t *model, char *remapFile ){
+       picoParser_t    *p;
+       picoByte_t      *remapBuffer;
+       int remapBufSize;
+
 
-int PicoRemapModel( picoModel_t *model, char *remapFile )
-{
-       picoParser_t    *p;
-       picoByte_t              *remapBuffer;
-       int                             remapBufSize;
-       
-       
        /* sanity checks */
-       if( model == NULL || remapFile == NULL )
+       if ( model == NULL || remapFile == NULL ) {
                return 0;
-       
+       }
+
        /* load remap file contents */
        _pico_load_file( remapFile,&remapBuffer,&remapBufSize );
-       
+
        /* check result */
-       if( remapBufSize == 0 )
-               return 1;       /* file is empty: no error */
-       if( remapBufSize < 0 )
-               return 0;       /* load failed: error */
-       
+       if ( remapBufSize == 0 ) {
+               return 1;   /* file is empty: no error */
+       }
+       if ( remapBufSize < 0 ) {
+               return 0;   /* load failed: error */
+
+       }
        /* create a new pico parser */
        p = _pico_new_parser( remapBuffer, remapBufSize );
-       if (p == NULL)
-       {
+       if ( p == NULL ) {
                /* ram is really cheap nowadays... */
                _prm_error_return;
        }
-       
+
        /* doo teh parse */
-       while( 1 )
+       while ( 1 )
        {
                /* get next token in remap file */
-               if (!_pico_parse( p,1 ))
+               if ( !_pico_parse( p,1 ) ) {
                        break;
+               }
 
                /* skip over c++ style comment lines */
-               if (!_pico_stricmp(p->token,"//"))
-               {
+               if ( !_pico_stricmp( p->token,"//" ) ) {
                        _pico_parse_skip_rest( p );
                        continue;
                }
-               
+
                /* block for quick material shader name remapping */
                /* materials { "m" (=>|->|=) "s" } */
-               if( !_pico_stricmp(p->token, "materials" ) )
-               {
+               if ( !_pico_stricmp( p->token, "materials" ) ) {
                        int level = 1;
 
                        /* check bracket */
-                       if (!_pico_parse_check( p,1,"{" ))
+                       if ( !_pico_parse_check( p,1,"{" ) ) {
                                _prm_error_return;
+                       }
 
                        /* process assignments */
-                       while( 1 )
+                       while ( 1 )
                        {
-                               picoShader_t    *shader;
-                               char                    *materialName;
-                               
-                               
+                               picoShader_t    *shader;
+                               char            *materialName;
+
+
                                /* get material name */
-                               if (_pico_parse( p,1 ) == NULL) break;
-                               if (!strlen(p->token)) continue;
-                               materialName = _pico_clone_alloc( p->token,-1 );
-                               if (materialName == NULL)
+                               if ( _pico_parse( p,1 ) == NULL ) {
+                                       break;
+                               }
+                               if ( !strlen( p->token ) ) {
+                                       continue;
+                               }
+                               materialName = _pico_clone_alloc( p->token );
+                               if ( materialName == NULL ) {
                                        _prm_error_return;
+                               }
 
                                /* handle levels */
-                               if (p->token[0] == '{') level++;
-                               if (p->token[0] == '}') level--;
-                               if (!level) break;
+                               if ( p->token[0] == '{' ) {
+                                       level++;
+                               }
+                               if ( p->token[0] == '}' ) {
+                                       level--;
+                               }
+                               if ( !level ) {
+                                       break;
+                               }
 
                                /* get next token (assignment token or shader name) */
-                               if (!_pico_parse( p,0 ))
-                               {
+                               if ( !_pico_parse( p,0 ) ) {
                                        _pico_free( materialName );
                                        _prm_error_return;
                                }
                                /* skip assignment token (if present) */
-                               if (!strcmp(p->token,"=>") ||
-                                       !strcmp(p->token,"->") ||
-                                       !strcmp(p->token,"="))
-                               {
+                               if ( !strcmp( p->token,"=>" ) ||
+                                        !strcmp( p->token,"->" ) ||
+                                        !strcmp( p->token,"=" ) ) {
                                        /* simply grab the next token */
-                                       if (!_pico_parse( p,0 ))
-                                       {
+                                       if ( !_pico_parse( p,0 ) ) {
                                                _pico_free( materialName );
                                                _prm_error_return;
                                        }
@@ -1777,8 +2091,7 @@ int PicoRemapModel( picoModel_t *model, char *remapFile )
                                shader = PicoFindShader( model,materialName,0 );
 
                                /* we've found a material matching the name */
-                               if (shader != NULL)
-                               {
+                               if ( shader != NULL ) {
                                        PicoSetShaderName( shader,p->token );
                                }
                                /* free memory used by material name */
@@ -1790,24 +2103,26 @@ int PicoRemapModel( picoModel_t *model, char *remapFile )
                }
                /* block for detailed single material remappings */
                /* materials[ "m" ] { key data... } */
-               else if (!_pico_stricmp(p->token,"materials["))
-               {
+               else if ( !_pico_stricmp( p->token,"materials[" ) ) {
                        picoShader_t *shader;
                        char *tempMaterialName;
                        int level = 1;
 
                        /* get material name */
-                       if (!_pico_parse( p,0 ))
+                       if ( !_pico_parse( p,0 ) ) {
                                _prm_error_return;
+                       }
 
                        /* temporary copy of material name */
-                       tempMaterialName = _pico_clone_alloc( p->token,-1 );
-                       if (tempMaterialName == NULL)
+                       tempMaterialName = _pico_clone_alloc( p->token );
+                       if ( tempMaterialName == NULL ) {
                                _prm_error_return;
+                       }
 
                        /* check square closing bracket */
-                       if (!_pico_parse_check( p,0,"]" ))
-                               _prm_error_return;                      
+                       if ( !_pico_parse_check( p,0,"]" ) ) {
+                               _prm_error_return;
+                       }
 
                        /* try to find material by name */
                        shader = PicoFindShader( model,tempMaterialName,0 );
@@ -1818,47 +2133,60 @@ int PicoRemapModel( picoModel_t *model, char *remapFile )
                        /* we haven't found a material matching the name */
                        /* so we simply skip the braced section now and */
                        /* continue parsing with the next main token */
-                       if (shader == NULL)
-                       {
+                       if ( shader == NULL ) {
                                _pico_parse_skip_braced( p );
                                continue;
                        }
                        /* check opening bracket */
-                       if (!_pico_parse_check( p,1,"{" ))
+                       if ( !_pico_parse_check( p,1,"{" ) ) {
                                _prm_error_return;
+                       }
 
                        /* process material info keys */
-                       while( 1 )
+                       while ( 1 )
                        {
                                /* get key name */
-                               if (_pico_parse( p,1 ) == NULL) break;
-                               if (!strlen(p->token)) continue;
+                               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 ( p->token[0] == '{' ) {
+                                       level++;
+                               }
+                               if ( p->token[0] == '}' ) {
+                                       level--;
+                               }
+                               if ( !level ) {
+                                       break;
+                               }
 
                                /* remap shader name */
-                               if (!_pico_stricmp(p->token,"shader"))
-                               {
-                                       if (!_pico_parse( p,0 )) _prm_error_return;
+                               if ( !_pico_stricmp( p->token,"shader" ) ) {
+                                       if ( !_pico_parse( p,0 ) ) {
+                                               _prm_error_return;
+                                       }
                                        PicoSetShaderName( shader,p->token );
                                }
                                /* remap shader map name */
-                               else if (!_pico_stricmp(p->token,"mapname"))
-                               {
-                                       if (!_pico_parse( p,0 )) _prm_error_return;
+                               else if ( !_pico_stricmp( p->token,"mapname" ) ) {
+                                       if ( !_pico_parse( p,0 ) ) {
+                                               _prm_error_return;
+                                       }
                                        PicoSetShaderMapName( shader,p->token );
                                }
                                /* remap shader's ambient color */
-                               else if (!_pico_stricmp(p->token,"ambient"))
-                               {
+                               else if ( !_pico_stricmp( p->token,"ambient" ) ) {
                                        picoColor_t color;
-                                       picoVec3_t  v;
+                                       picoVec3_t v;
 
                                        /* get vector from parser */
-                                       if (!_pico_parse_vec( p,v )) _prm_error_return;
+                                       if ( !_pico_parse_vec( p,v ) ) {
+                                               _prm_error_return;
+                                       }
 
                                        /* store as color */
                                        color[ 0 ] = (picoByte_t)v[ 0 ];
@@ -1869,13 +2197,14 @@ int PicoRemapModel( picoModel_t *model, char *remapFile )
                                        PicoSetShaderAmbientColor( shader,color );
                                }
                                /* remap shader's diffuse color */
-                               else if (!_pico_stricmp(p->token,"diffuse"))
-                               {
+                               else if ( !_pico_stricmp( p->token,"diffuse" ) ) {
                                        picoColor_t color;
-                                       picoVec3_t  v;
+                                       picoVec3_t v;
 
                                        /* get vector from parser */
-                                       if (!_pico_parse_vec( p,v )) _prm_error_return;
+                                       if ( !_pico_parse_vec( p,v ) ) {
+                                               _prm_error_return;
+                                       }
 
                                        /* store as color */
                                        color[ 0 ] = (picoByte_t)v[ 0 ];
@@ -1886,13 +2215,14 @@ int PicoRemapModel( picoModel_t *model, char *remapFile )
                                        PicoSetShaderDiffuseColor( shader,color );
                                }
                                /* remap shader's specular color */
-                               else if (!_pico_stricmp(p->token,"specular"))
-                               {
+                               else if ( !_pico_stricmp( p->token,"specular" ) ) {
                                        picoColor_t color;
-                                       picoVec3_t  v;
+                                       picoVec3_t v;
 
                                        /* get vector from parser */
-                                       if (!_pico_parse_vec( p,v )) _prm_error_return;
+                                       if ( !_pico_parse_vec( p,v ) ) {
+                                               _prm_error_return;
+                                       }
 
                                        /* store as color */
                                        color[ 0 ] = (picoByte_t)v[ 0 ];
@@ -1908,7 +2238,7 @@ int PicoRemapModel( picoModel_t *model, char *remapFile )
                }
                /* end 'materials[' */
        }
-       
+
        /* free both parser and file buffer */
        _pico_free_parser( p );
        _pico_free_file( remapBuffer );
@@ -1919,15 +2249,14 @@ int PicoRemapModel( picoModel_t *model, char *remapFile )
 
 
 /*
-PicoAddTriangleToModel() - jhefty
-A nice way to add individual triangles to the model.
-Chooses an appropriate surface based on the shader, or adds a new surface if necessary
-*/
-
-void PicoAddTriangleToModel( picoModel_t *model, picoVec3_t** xyz, picoVec3_t** normals, 
-                                                       int numSTs, picoVec2_t **st, int numColors, picoColor_t **colors,
-                                                       picoShader_t* shader )
-{
+   PicoAddTriangleToModel() - jhefty
+   A nice way to add individual triangles to the model.
+   Chooses an appropriate surface based on the shader, or adds a new surface if necessary
+ */
+
+void PicoAddTriangleToModel( picoModel_t *model, picoVec3_t** xyz, picoVec3_t** normals,
+                                                        int numSTs, picoVec2_t **st, int numColors, picoColor_t **colors,
+                                                        picoShader_t* shader, const char *name, picoIndex_t* smoothingGroup ){
        int i,j;
        int vertDataIndex;
        picoSurface_t* workSurface = NULL;
@@ -1936,60 +2265,60 @@ void PicoAddTriangleToModel( picoModel_t *model, picoVec3_t** xyz, picoVec3_t**
        for ( i = 0 ; i < model->numSurfaces ; i++ )
        {
                workSurface = model->surface[i];
-               if ( workSurface->shader == shader )
-               {                       
-                       break;
+               if ( !name || !strcmp( workSurface->name, name ) ) {
+                       if ( workSurface->shader == shader ) {
+                               break;
+                       }
                }
        }
 
        /* no surface uses this shader yet, so create a new surface */
-       if ( !workSurface || i >=model->numSurfaces )
-       {
+       if ( !workSurface || i >= model->numSurfaces ) {
                /* create a new surface in the model for the unique shader */
-               workSurface = PicoNewSurface(model);
-               if ( !workSurface )
-               {
-                       _pico_printf ( PICO_ERROR , "Could not allocate a new surface!\n" );
+               workSurface = PicoNewSurface( model );
+               if ( !workSurface ) {
+                       _pico_printf( PICO_ERROR, "Could not allocate a new surface!\n" );
                        return;
                }
 
                /* do surface setup */
                PicoSetSurfaceType( workSurface, PICO_TRIANGLES );
-               PicoSetSurfaceName( workSurface, shader->name );
+               PicoSetSurfaceName( workSurface, name ? name : shader->name );
                PicoSetSurfaceShader( workSurface, shader );
        }
 
        /* add the triangle data to the surface */
-       for ( i = 0 ; i < 3 ; i++ )     
+       for ( i = 0 ; i < 3 ; i++ )
        {
                /* get the next free spot in the index array */
-               int newVertIndex = PicoGetSurfaceNumIndexes ( workSurface );
+               int newVertIndex = PicoGetSurfaceNumIndexes( workSurface );
 
                /* get the index of the vertex that we're going to store at newVertIndex */
-               vertDataIndex = PicoFindSurfaceVertexNum ( workSurface , *xyz[i] , *normals[i] , numSTs , st[i] , numColors , colors[i]);
+               vertDataIndex = PicoFindSurfaceVertexNum( workSurface, *xyz[i], *normals[i], numSTs, st[i], numColors, colors[i], smoothingGroup[i] );
 
                /* the vertex wasn't found, so create a new vertex in the pool from the data we have */
-               if ( vertDataIndex == -1 )
-               {                       
+               if ( vertDataIndex == -1 ) {
                        /* find the next spot for a new vertex */
-                       vertDataIndex = PicoGetSurfaceNumVertexes ( workSurface );                      
+                       vertDataIndex = PicoGetSurfaceNumVertexes( workSurface );
 
                        /* assign the data to it */
-                       PicoSetSurfaceXYZ ( workSurface ,vertDataIndex , *xyz[i] );
-                       PicoSetSurfaceNormal ( workSurface , vertDataIndex , *normals[i] );                     
+                       PicoSetSurfaceXYZ( workSurface,vertDataIndex, *xyz[i] );
+                       PicoSetSurfaceNormal( workSurface, vertDataIndex, *normals[i] );
 
                        /* make sure to copy over all available ST's and colors for the vertex */
                        for ( j = 0 ; j < numColors ; j++ )
                        {
-                               PicoSetSurfaceColor( workSurface , j , vertDataIndex , colors[i][j] );
+                               PicoSetSurfaceColor( workSurface, j, vertDataIndex, colors[i][j] );
                        }
                        for ( j = 0 ; j < numSTs ; j++ )
                        {
-                               PicoSetSurfaceST ( workSurface , j , vertDataIndex , st[i][j] );
+                               PicoSetSurfaceST( workSurface, j, vertDataIndex, st[i][j] );
                        }
+
+                       PicoSetSurfaceSmoothingGroup( workSurface, vertDataIndex, smoothingGroup[i] );
                }
 
-               /* add this vertex to the triangle */           
-               PicoSetSurfaceIndex ( workSurface , newVertIndex , vertDataIndex );
-       }       
+               /* add this vertex to the triangle */
+               PicoSetSurfaceIndex( workSurface, newVertIndex, vertDataIndex );
+       }
 }