1 /* -----------------------------------------------------------------------------
5 Copyright (c) 2002, Randy Reddig & seaw0lf
8 Redistribution and use in source and binary forms, with or without modification,
9 are permitted provided that the following conditions are met:
11 Redistributions of source code must retain the above copyright notice, this list
12 of conditions and the following disclaimer.
14 Redistributions in binary form must reproduce the above copyright notice, this
15 list of conditions and the following disclaimer in the documentation and/or
16 other materials provided with the distribution.
18 Neither the names of the copyright holders nor the names of its contributors may
19 be used to endorse or promote products derived from this software without
20 specific prior written permission.
22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
23 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
26 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
29 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 ----------------------------------------------------------------------------- */
43 #include "picointernal.h"
49 initializes the picomodel library
54 /* successfully initialized -sea */
62 shuts the pico model library down
65 void PicoShutdown( void )
67 /* do something interesting here in the future */
75 returns last picomodel error code (see PME_* defines)
80 /* todo: do something here */
88 sets the ptr to the malloc function
91 void PicoSetMallocFunc( void *(*func)( size_t ) )
94 _pico_ptr_malloc = func;
101 sets the ptr to the free function
104 void PicoSetFreeFunc( void (*func)( void* ) )
107 _pico_ptr_free = func;
113 PicoSetLoadFileFunc()
114 sets the ptr to the file load function
117 void PicoSetLoadFileFunc( void (*func)( char*, unsigned char**, int* ) )
120 _pico_ptr_load_file = func;
126 PicoSetFreeFileFunc()
127 sets the ptr to the free function
130 void PicoSetFreeFileFunc( void (*func)( void* ) )
133 _pico_ptr_free_file = func;
140 sets the ptr to the print function
143 void PicoSetPrintFunc( void (*func)( int, const char* ) )
146 _pico_ptr_print = func;
151 picoModel_t *PicoModuleLoadModel( const picoModule_t* pm, char* fileName, picoByte_t* buffer, int bufSize, int frameNum )
153 char *modelFileName, *remapFileName;
155 /* see whether this module can load the model file or not */
156 if( pm->canload( fileName, buffer, bufSize ) == PICO_PMV_OK )
158 /* use loader provided by module to read the model data */
159 picoModel_t* model = pm->load( fileName, frameNum, buffer, bufSize );
162 _pico_free_file( buffer );
166 /* assign pointer to file format module */
169 /* get model file name */
170 modelFileName = PicoGetModelFileName( model );
172 /* apply model remappings from <model>.remap */
173 if( strlen( modelFileName ) )
175 /* alloc copy of model file name */
176 remapFileName = _pico_alloc( strlen( modelFileName ) + 20 );
177 if( remapFileName != NULL )
179 /* copy model file name and change extension */
180 strcpy( remapFileName, modelFileName );
181 _pico_setfext( remapFileName, "remap" );
183 /* try to remap model; we don't handle the result */
184 PicoRemapModel( model, remapFileName );
186 /* free the remap file name string */
187 _pico_free( remapFileName );
199 the meat and potatoes function
202 picoModel_t *PicoLoadModel( char *fileName, int frameNum )
204 const picoModule_t **modules, *pm;
213 /* make sure we've got a file name */
214 if( fileName == NULL )
216 _pico_printf( PICO_ERROR, "PicoLoadModel: No filename given (fileName == NULL)" );
220 /* load file data (buffer is allocated by host app) */
221 _pico_load_file( fileName, &buffer, &bufSize );
224 _pico_printf( PICO_ERROR, "PicoLoadModel: Failed loading model %s", fileName );
228 /* get ptr to list of supported modules */
229 modules = PicoModuleList( NULL );
231 /* run it through the various loader functions and try */
232 /* to find a loader that fits the given file data */
233 for( ; *modules != NULL; modules++ )
242 /* module must be able to load */
243 if( pm->canload == NULL || pm->load == NULL )
246 model = PicoModuleLoadModel(pm, fileName, buffer, bufSize, frameNum);
249 /* model was loaded, so break out of loop */
254 /* free memory used by file buffer */
256 _pico_free_file( buffer );
262 picoModel_t *PicoModuleLoadModelStream( const picoModule_t* module, void* inputStream, PicoInputStreamReadFunc inputStreamRead, size_t streamLength, int frameNum )
272 if( inputStream == NULL )
274 _pico_printf( PICO_ERROR, "PicoLoadModel: invalid input stream (inputStream == NULL)" );
278 if( inputStreamRead == NULL )
280 _pico_printf( PICO_ERROR, "PicoLoadModel: invalid input stream (inputStreamRead == NULL)" );
284 buffer = _pico_alloc(streamLength + 1);
286 bufSize = (int)inputStreamRead(inputStream, buffer, streamLength);
287 buffer[bufSize] = '\0';
293 strncpy(fileName + 1, module->defaultExts[0], 126);
294 fileName[127] = '\0';
295 model = PicoModuleLoadModel(module, fileName, buffer, bufSize, frameNum);
305 /* ----------------------------------------------------------------------------
307 ---------------------------------------------------------------------------- */
311 creates a new pico model
314 picoModel_t *PicoNewModel( void )
319 model = _pico_alloc( sizeof(picoModel_t) );
324 memset( model,0,sizeof(picoModel_t) );
327 _pico_zero_bounds( model->mins,model->maxs );
329 /* set initial frame count to 1 -sea */
330 model->numFrames = 1;
332 /* return ptr to new model */
340 frees a model and all associated data
343 void PicoFreeModel( picoModel_t *model )
354 _pico_free( model->name );
356 if( model->fileName )
357 _pico_free( model->fileName );
360 for( i = 0; i < model->numShaders; i++ )
361 PicoFreeShader( model->shader[ i ] );
362 free( model->shader );
365 for( i = 0; i < model->numSurfaces; i++ )
366 PicoFreeSurface( model->surface[ i ] );
367 free( model->surface );
377 adjusts a models's memory allocations to handle the requested sizes.
378 will always grow, never shrink
381 int PicoAdjustModel( picoModel_t *model, int numShaders, int numSurfaces )
388 /* sea: null surface/shader fix (1s=>0s) */
391 if( numSurfaces < 0 )
394 /* additional shaders? */
395 while( numShaders > model->maxShaders )
397 model->maxShaders += PICO_GROW_SHADERS;
398 if( !_pico_realloc( (void *) &model->shader, model->numShaders * sizeof( *model->shader ), model->maxShaders * sizeof( *model->shader ) ) )
402 /* set shader count to higher */
403 if( numShaders > model->numShaders )
404 model->numShaders = numShaders;
406 /* additional surfaces? */
407 while( numSurfaces > model->maxSurfaces )
409 model->maxSurfaces += PICO_GROW_SURFACES;
410 if( !_pico_realloc( (void *) &model->surface, model->numSurfaces * sizeof( *model->surface ), model->maxSurfaces * sizeof( *model->surface ) ) )
414 /* set shader count to higher */
415 if( numSurfaces > model->numSurfaces )
416 model->numSurfaces = numSurfaces;
424 /* ----------------------------------------------------------------------------
426 ---------------------------------------------------------------------------- */
430 creates a new pico shader and returns its index. -sea
433 picoShader_t *PicoNewShader( picoModel_t *model )
435 picoShader_t *shader;
438 /* allocate and clear */
439 shader = _pico_alloc( sizeof(picoShader_t) );
442 memset( shader, 0, sizeof(picoShader_t) );
444 /* attach it to the model */
448 if( !PicoAdjustModel( model, model->numShaders + 1, 0 ) )
450 _pico_free( shader );
455 model->shader[ model->numShaders - 1 ] = shader;
456 shader->model = model;
459 /* setup default shader colors */
460 _pico_set_color( shader->ambientColor,0,0,0,0 );
461 _pico_set_color( shader->diffuseColor,255,255,255,1 );
462 _pico_set_color( shader->specularColor,0,0,0,0 );
464 /* no need to do this, but i do it anyway */
465 shader->transparency = 0;
466 shader->shininess = 0;
468 /* return the newly created shader */
476 frees a shader and all associated data -sea
479 void PicoFreeShader( picoShader_t *shader )
487 _pico_free( shader->name );
488 if( shader->mapName )
489 _pico_free( shader->mapName );
491 /* free the shader */
492 _pico_free( shader );
499 finds a named shader in a model
502 picoShader_t *PicoFindShader( picoModel_t *model, char *name, int caseSensitive )
508 if( model == NULL || name == NULL ) /* sea: null name fix */
512 for( i = 0; i < model->numShaders; i++ )
514 /* skip null shaders or shaders with null names */
515 if( model->shader[ i ] == NULL ||
516 model->shader[ i ]->name == NULL )
519 /* compare the shader name with name we're looking for */
522 if( !strcmp( name, model->shader[ i ]->name ) )
523 return model->shader[ i ];
525 else if( !_pico_stricmp( name, model->shader[ i ]->name ) )
526 return model->shader[ i ];
529 /* named shader not found */
535 /* ----------------------------------------------------------------------------
537 ---------------------------------------------------------------------------- */
541 creates a new pico surface
544 picoSurface_t *PicoNewSurface( picoModel_t *model )
546 picoSurface_t *surface;
547 char surfaceName[64];
549 /* allocate and clear */
550 surface = _pico_alloc( sizeof( *surface ) );
551 if( surface == NULL )
553 memset( surface, 0, sizeof( *surface ) );
555 /* attach it to the model */
559 if( !PicoAdjustModel( model, 0, model->numSurfaces + 1 ) )
561 _pico_free( surface );
566 model->surface[ model->numSurfaces - 1 ] = surface;
567 surface->model = model;
569 /* set default name */
570 sprintf( surfaceName, "Unnamed_%d", model->numSurfaces );
571 PicoSetSurfaceName( surface, surfaceName );
582 frees a surface and all associated data
584 void PicoFreeSurface( picoSurface_t *surface )
590 if( surface == NULL )
594 _pico_free( surface->xyz );
595 _pico_free( surface->normal );
596 _pico_free( surface->smoothingGroup );
597 _pico_free( surface->index );
598 _pico_free( surface->faceNormal );
601 _pico_free( surface->name );
604 for( i = 0; i < surface->numSTArrays; i++ )
605 _pico_free( surface->st[ i ] );
607 for( i = 0; i < surface->numColorArrays; i++ )
608 _pico_free( surface->color[ i ] );
609 free( surface->color );
611 /* free the surface */
612 _pico_free( surface );
619 adjusts a surface's memory allocations to handle the requested sizes.
620 will always grow, never shrink
623 int PicoAdjustSurface( picoSurface_t *surface, int numVertexes, int numSTArrays, int numColorArrays, int numIndexes, int numFaceNormals )
629 if( surface == NULL )
633 if( numVertexes < 1 )
635 if( numSTArrays < 1 )
637 if( numColorArrays < 1 )
642 /* additional vertexes? */
643 while( numVertexes > surface->maxVertexes ) /* fix */
645 surface->maxVertexes += PICO_GROW_VERTEXES;
646 if( !_pico_realloc( (void *) &surface->xyz, surface->numVertexes * sizeof( *surface->xyz ), surface->maxVertexes * sizeof( *surface->xyz ) ) )
648 if( !_pico_realloc( (void *) &surface->normal, surface->numVertexes * sizeof( *surface->normal ), surface->maxVertexes * sizeof( *surface->normal ) ) )
650 if( !_pico_realloc( (void *) &surface->smoothingGroup, surface->numVertexes * sizeof( *surface->smoothingGroup ), surface->maxVertexes * sizeof( *surface->smoothingGroup ) ) )
652 for( i = 0; i < surface->numSTArrays; i++ )
653 if( !_pico_realloc( (void*) &surface->st[ i ], surface->numVertexes * sizeof( *surface->st[ i ] ), surface->maxVertexes * sizeof( *surface->st[ i ] ) ) )
655 for( i = 0; i < surface->numColorArrays; i++ )
656 if( !_pico_realloc( (void*) &surface->color[ i ], surface->numVertexes * sizeof( *surface->color[ i ] ), surface->maxVertexes * sizeof( *surface->color[ i ] ) ) )
660 /* set vertex count to higher */
661 if( numVertexes > surface->numVertexes )
662 surface->numVertexes = numVertexes;
664 /* additional st arrays? */
665 while( numSTArrays > surface->maxSTArrays ) /* fix */
667 surface->maxSTArrays += PICO_GROW_ARRAYS;
668 if( !_pico_realloc( (void*) &surface->st, surface->numSTArrays * sizeof( *surface->st ), surface->maxSTArrays * sizeof( *surface->st ) ) )
670 while( surface->numSTArrays < numSTArrays )
672 surface->st[ surface->numSTArrays ] = _pico_alloc( surface->maxVertexes * sizeof( *surface->st[ 0 ] ) );
673 memset( surface->st[ surface->numSTArrays ], 0, surface->maxVertexes * sizeof( *surface->st[ 0 ] ) );
674 surface->numSTArrays++;
678 /* additional color arrays? */
679 while( numColorArrays > surface->maxColorArrays ) /* fix */
681 surface->maxColorArrays += PICO_GROW_ARRAYS;
682 if( !_pico_realloc( (void*) &surface->color, surface->numColorArrays * sizeof( *surface->color ), surface->maxColorArrays * sizeof( *surface->color ) ) )
684 while( surface->numColorArrays < numColorArrays )
686 surface->color[ surface->numColorArrays ] = _pico_alloc( surface->maxVertexes * sizeof( *surface->color[ 0 ] ) );
687 memset( surface->color[ surface->numColorArrays ], 0, surface->maxVertexes * sizeof( *surface->color[ 0 ] ) );
688 surface->numColorArrays++;
692 /* additional indexes? */
693 while( numIndexes > surface->maxIndexes ) /* fix */
695 surface->maxIndexes += PICO_GROW_INDEXES;
696 if( !_pico_realloc( (void*) &surface->index, surface->numIndexes * sizeof( *surface->index ), surface->maxIndexes * sizeof( *surface->index ) ) )
700 /* set index count to higher */
701 if( numIndexes > surface->numIndexes )
702 surface->numIndexes = numIndexes;
704 /* additional face normals? */
705 while( numFaceNormals > surface->maxFaceNormals ) /* fix */
707 surface->maxFaceNormals += PICO_GROW_FACES;
708 if( !_pico_realloc( (void *) &surface->faceNormal, surface->numFaceNormals * sizeof( *surface->faceNormal ), surface->maxFaceNormals * sizeof( *surface->faceNormal ) ) )
712 /* set face normal count to higher */
713 if( numFaceNormals > surface->numFaceNormals )
714 surface->numFaceNormals = numFaceNormals;
722 * Finds first matching named surface in a model.
724 picoSurface_t *PicoFindSurface(
725 picoModel_t *model, char *name, int caseSensitive )
730 if( model == NULL || name == NULL )
734 for( i = 0; i < model->numSurfaces; i++ )
736 /* skip null surfaces or surfaces with null names */
737 if( model->surface[ i ] == NULL ||
738 model->surface[ i ]->name == NULL )
741 /* compare the surface name with name we're looking for */
743 if( !strcmp(name,model->surface[ i ]->name) )
744 return model->surface[ i ];
746 if( !_pico_stricmp(name,model->surface[ i ]->name) )
747 return model->surface[ i ];
750 /* named surface not found */
756 /*----------------------------------------------------------------------------
757 PicoSet*() Setter Functions
758 ----------------------------------------------------------------------------*/
760 void PicoSetModelName( picoModel_t *model, char *name )
762 if( model == NULL || name == NULL )
764 if( model->name != NULL )
765 _pico_free( model->name );
767 model->name = _pico_clone_alloc( name );
772 void PicoSetModelFileName( picoModel_t *model, char *fileName )
774 if( model == NULL || fileName == NULL )
776 if( model->fileName != NULL )
777 _pico_free( model->fileName );
779 model->fileName = _pico_clone_alloc( fileName );
784 void PicoSetModelFrameNum( picoModel_t *model, int frameNum )
788 model->frameNum = frameNum;
793 void PicoSetModelNumFrames( picoModel_t *model, int numFrames )
797 model->numFrames = numFrames;
802 void PicoSetModelData( picoModel_t *model, void *data )
811 void PicoSetShaderName( picoShader_t *shader, char *name )
813 if( shader == NULL || name == NULL )
815 if( shader->name != NULL )
816 _pico_free( shader->name );
818 shader->name = _pico_clone_alloc( name );
823 void PicoSetShaderMapName( picoShader_t *shader, char *mapName )
825 if( shader == NULL || mapName == NULL )
827 if( shader->mapName != NULL )
828 _pico_free( shader->mapName );
830 shader->mapName = _pico_clone_alloc( mapName );
835 void PicoSetShaderAmbientColor( picoShader_t *shader, picoColor_t color )
837 if( shader == NULL || color == NULL )
839 shader->ambientColor[ 0 ] = color[ 0 ];
840 shader->ambientColor[ 1 ] = color[ 1 ];
841 shader->ambientColor[ 2 ] = color[ 2 ];
842 shader->ambientColor[ 3 ] = color[ 3 ];
847 void PicoSetShaderDiffuseColor( picoShader_t *shader, picoColor_t color )
849 if( shader == NULL || color == NULL )
851 shader->diffuseColor[ 0 ] = color[ 0 ];
852 shader->diffuseColor[ 1 ] = color[ 1 ];
853 shader->diffuseColor[ 2 ] = color[ 2 ];
854 shader->diffuseColor[ 3 ] = color[ 3 ];
859 void PicoSetShaderSpecularColor( picoShader_t *shader, picoColor_t color )
861 if( shader == NULL || color == NULL )
863 shader->specularColor[ 0 ] = color[ 0 ];
864 shader->specularColor[ 1 ] = color[ 1 ];
865 shader->specularColor[ 2 ] = color[ 2 ];
866 shader->specularColor[ 3 ] = color[ 3 ];
871 void PicoSetShaderTransparency( picoShader_t *shader, float value )
875 shader->transparency = value;
877 /* cap to 0..1 range */
878 if (shader->transparency < 0.0)
879 shader->transparency = 0.0;
880 if (shader->transparency > 1.0)
881 shader->transparency = 1.0;
886 void PicoSetShaderShininess( picoShader_t *shader, float value )
890 shader->shininess = value;
892 /* cap to 0..127 range */
893 if (shader->shininess < 0.0)
894 shader->shininess = 0.0;
895 if (shader->shininess > 127.0)
896 shader->shininess = 127.0;
901 void PicoSetSurfaceData( picoSurface_t *surface, void *data )
903 if( surface == NULL )
905 surface->data = data;
910 void PicoSetSurfaceType( picoSurface_t *surface, picoSurfaceType_t type )
912 if( surface == NULL )
914 surface->type = type;
919 void PicoSetSurfaceName( picoSurface_t *surface, char *name )
921 if( surface == NULL || name == NULL )
923 if( surface->name != NULL )
924 _pico_free( surface->name );
926 surface->name = _pico_clone_alloc( name );
931 void PicoSetSurfaceShader( picoSurface_t *surface, picoShader_t *shader )
933 if( surface == NULL )
935 surface->shader = shader;
940 void PicoSetSurfaceXYZ( picoSurface_t *surface, int num, picoVec3_t xyz )
942 if( surface == NULL || num < 0 || xyz == NULL )
944 if( !PicoAdjustSurface( surface, num + 1, 0, 0, 0, 0 ) )
946 _pico_copy_vec( xyz, surface->xyz[ num ] );
947 if( surface->model != NULL )
948 _pico_expand_bounds( xyz, surface->model->mins, surface->model->maxs );
953 void PicoSetSurfaceNormal( picoSurface_t *surface, int num, picoVec3_t normal )
955 if( surface == NULL || num < 0 || normal == NULL )
957 if( !PicoAdjustSurface( surface, num + 1, 0, 0, 0, 0 ) )
959 _pico_copy_vec( normal, surface->normal[ num ] );
964 void PicoSetSurfaceST( picoSurface_t *surface, int array, int num, picoVec2_t st )
966 if( surface == NULL || num < 0 || st == NULL )
968 if( !PicoAdjustSurface( surface, num + 1, array + 1, 0, 0, 0 ) )
970 surface->st[ array ][ num ][ 0 ] = st[ 0 ];
971 surface->st[ array ][ num ][ 1 ] = st[ 1 ];
976 void PicoSetSurfaceColor( picoSurface_t *surface, int array, int num, picoColor_t color )
978 if( surface == NULL || num < 0 || color == NULL )
980 if( !PicoAdjustSurface( surface, num + 1, 0, array + 1, 0, 0 ) )
982 surface->color[ array ][ num ][ 0 ] = color[ 0 ];
983 surface->color[ array ][ num ][ 1 ] = color[ 1 ];
984 surface->color[ array ][ num ][ 2 ] = color[ 2 ];
985 surface->color[ array ][ num ][ 3 ] = color[ 3 ];
990 void PicoSetSurfaceIndex( picoSurface_t *surface, int num, picoIndex_t index )
992 if( surface == NULL || num < 0 )
994 if( !PicoAdjustSurface( surface, 0, 0, 0, num + 1, 0 ) )
996 surface->index[ num ] = index;
1001 void PicoSetSurfaceIndexes( picoSurface_t *surface, int num, picoIndex_t *index, int count )
1003 if( num < 0 || index == NULL || count < 1 )
1005 if( !PicoAdjustSurface( surface, 0, 0, 0, num + count, 0 ) )
1007 memcpy( &surface->index[ num ], index, count * sizeof( surface->index[ num ] ) );
1012 void PicoSetFaceNormal( picoSurface_t *surface, int num, picoVec3_t normal )
1014 if( surface == NULL || num < 0 || normal == NULL )
1016 if( !PicoAdjustSurface( surface, 0, 0, 0, 0, num + 1 ) )
1018 _pico_copy_vec( normal, surface->faceNormal[ num ] );
1022 void PicoSetSurfaceSmoothingGroup( picoSurface_t *surface, int num, picoIndex_t smoothingGroup )
1026 if( !PicoAdjustSurface( surface, num + 1, 0, 0, 0, 0 ) )
1028 surface->smoothingGroup[ num ] = smoothingGroup;
1032 void PicoSetSurfaceSpecial( picoSurface_t *surface, int num, int special )
1034 if( surface == NULL || num < 0 || num >= PICO_MAX_SPECIAL )
1036 surface->special[ num ] = special;
1041 /*----------------------------------------------------------------------------
1042 PicoGet*() Getter Functions
1043 ----------------------------------------------------------------------------*/
1045 char *PicoGetModelName( picoModel_t *model )
1049 if( model->name == NULL)
1056 char *PicoGetModelFileName( picoModel_t *model )
1060 if( model->fileName == NULL)
1062 return model->fileName;
1067 int PicoGetModelFrameNum( picoModel_t *model )
1071 return model->frameNum;
1076 int PicoGetModelNumFrames( picoModel_t *model )
1080 return model->numFrames;
1085 void *PicoGetModelData( picoModel_t *model )
1094 int PicoGetModelNumShaders( picoModel_t *model )
1098 return model->numShaders;
1103 picoShader_t *PicoGetModelShader( picoModel_t *model, int num )
1105 /* a few sanity checks */
1108 if( model->shader == NULL)
1110 if( num < 0 || num >= model->numShaders )
1113 /* return the shader */
1114 return model->shader[ num ];
1119 int PicoGetModelNumSurfaces( picoModel_t *model )
1123 return model->numSurfaces;
1128 picoSurface_t *PicoGetModelSurface( picoModel_t *model, int num )
1130 /* a few sanity checks */
1133 if( model->surface == NULL)
1135 if( num < 0 || num >= model->numSurfaces )
1138 /* return the surface */
1139 return model->surface[ num ];
1144 int PicoGetModelTotalVertexes( picoModel_t *model )
1151 if( model->surface == NULL )
1155 for( i = 0; i < model->numSurfaces; i++ )
1156 count += PicoGetSurfaceNumVertexes( model->surface[ i ] );
1163 int PicoGetModelTotalIndexes( picoModel_t *model )
1170 if( model->surface == NULL )
1174 for( i = 0; i < model->numSurfaces; i++ )
1175 count += PicoGetSurfaceNumIndexes( model->surface[ i ] );
1182 char *PicoGetShaderName( picoShader_t *shader )
1184 if( shader == NULL )
1186 if( shader->name == NULL)
1188 return shader->name;
1193 char *PicoGetShaderMapName( picoShader_t *shader )
1195 if( shader == NULL )
1197 if( shader->mapName == NULL)
1199 return shader->mapName;
1204 picoByte_t *PicoGetShaderAmbientColor( picoShader_t *shader )
1206 if( shader == NULL )
1208 return shader->ambientColor;
1213 picoByte_t *PicoGetShaderDiffuseColor( picoShader_t *shader )
1215 if( shader == NULL )
1217 return shader->diffuseColor;
1222 picoByte_t *PicoGetShaderSpecularColor( picoShader_t *shader )
1224 if( shader == NULL )
1226 return shader->specularColor;
1231 float PicoGetShaderTransparency( picoShader_t *shader )
1233 if( shader == NULL )
1235 return shader->transparency;
1240 float PicoGetShaderShininess( picoShader_t *shader )
1242 if( shader == NULL )
1244 return shader->shininess;
1249 void *PicoGetSurfaceData( picoSurface_t *surface )
1251 if( surface == NULL )
1253 return surface->data;
1258 picoSurfaceType_t PicoGetSurfaceType( picoSurface_t *surface )
1260 if( surface == NULL )
1262 return surface->type;
1267 char *PicoGetSurfaceName( picoSurface_t *surface )
1269 if( surface == NULL )
1271 if( surface->name == NULL )
1273 return surface->name;
1278 picoShader_t *PicoGetSurfaceShader( picoSurface_t *surface )
1280 if( surface == NULL )
1282 return surface->shader;
1287 int PicoGetSurfaceNumVertexes( picoSurface_t *surface )
1289 if( surface == NULL )
1291 return surface->numVertexes;
1296 picoVec_t *PicoGetSurfaceXYZ( picoSurface_t *surface, int num )
1298 if( surface == NULL || num < 0 || num > surface->numVertexes )
1300 return surface->xyz[ num ];
1305 picoVec_t *PicoGetSurfaceNormal( picoSurface_t *surface, int num )
1307 if( surface == NULL || num < 0 || num > surface->numVertexes )
1309 return surface->normal[ num ];
1314 picoVec_t *PicoGetSurfaceST( picoSurface_t *surface, int array, int num )
1316 if( surface == NULL || array < 0 || array > surface->numSTArrays || num < 0 || num > surface->numVertexes )
1318 return surface->st[ array ][ num ];
1323 picoByte_t *PicoGetSurfaceColor( picoSurface_t *surface, int array, int num )
1325 if( surface == NULL || array < 0 || array > surface->numColorArrays || num < 0 || num > surface->numVertexes )
1327 return surface->color[ array ][ num ];
1332 int PicoGetSurfaceNumIndexes( picoSurface_t *surface )
1334 if( surface == NULL )
1336 return surface->numIndexes;
1341 picoIndex_t PicoGetSurfaceIndex( picoSurface_t *surface, int num )
1343 if( surface == NULL || num < 0 || num > surface->numIndexes )
1345 return surface->index[ num ];
1350 picoIndex_t *PicoGetSurfaceIndexes( picoSurface_t *surface, int num )
1352 if( surface == NULL || num < 0 || num > surface->numIndexes )
1354 return &surface->index[ num ];
1358 picoVec_t *PicoGetFaceNormal( picoSurface_t *surface, int num )
1360 if( surface == NULL || num < 0 || num > surface->numFaceNormals )
1362 return surface->faceNormal[ num ];
1365 picoIndex_t PicoGetSurfaceSmoothingGroup( picoSurface_t *surface, int num )
1367 if( surface == NULL || num < 0 || num > surface->numVertexes )
1369 return surface->smoothingGroup[ num ];
1373 int PicoGetSurfaceSpecial( picoSurface_t *surface, int num )
1375 if( surface == NULL || num < 0 || num >= PICO_MAX_SPECIAL )
1377 return surface->special[ num ];
1382 /* ----------------------------------------------------------------------------
1383 hashtable related functions
1384 ---------------------------------------------------------------------------- */
1386 /* hashtable code for faster vertex lookups */
1387 //#define HASHTABLE_SIZE 32768 // 2048 /* power of 2, use & */
1388 #define HASHTABLE_SIZE 7919 // 32749 // 2039 /* prime, use % */
1390 int PicoGetHashTableSize( void )
1392 return HASHTABLE_SIZE;
1395 #define HASH_USE_EPSILON
1397 #ifdef HASH_USE_EPSILON
1398 #define HASH_XYZ_EPSILON 0.01f
1399 #define HASH_XYZ_EPSILONSPACE_MULTIPLIER 1.f / HASH_XYZ_EPSILON
1400 #define HASH_ST_EPSILON 0.0001f
1401 #define HASH_NORMAL_EPSILON 0.02f
1404 unsigned int PicoVertexCoordGenerateHash( picoVec3_t xyz )
1406 unsigned int hash = 0;
1408 #ifndef HASH_USE_EPSILON
1409 hash += ~(*((unsigned int*) &xyz[ 0 ]) << 15);
1410 hash ^= (*((unsigned int*) &xyz[ 0 ]) >> 10);
1411 hash += (*((unsigned int*) &xyz[ 1 ]) << 3);
1412 hash ^= (*((unsigned int*) &xyz[ 1 ]) >> 6);
1413 hash += ~(*((unsigned int*) &xyz[ 2 ]) << 11);
1414 hash ^= (*((unsigned int*) &xyz[ 2 ]) >> 16);
1416 picoVec3_t xyz_epsilonspace;
1418 _pico_scale_vec( xyz, HASH_XYZ_EPSILONSPACE_MULTIPLIER, xyz_epsilonspace );
1419 xyz_epsilonspace[ 0 ] = (float)floor(xyz_epsilonspace[ 0 ]);
1420 xyz_epsilonspace[ 1 ] = (float)floor(xyz_epsilonspace[ 1 ]);
1421 xyz_epsilonspace[ 2 ] = (float)floor(xyz_epsilonspace[ 2 ]);
1423 hash += ~(*((unsigned int*) &xyz_epsilonspace[ 0 ]) << 15);
1424 hash ^= (*((unsigned int*) &xyz_epsilonspace[ 0 ]) >> 10);
1425 hash += (*((unsigned int*) &xyz_epsilonspace[ 1 ]) << 3);
1426 hash ^= (*((unsigned int*) &xyz_epsilonspace[ 1 ]) >> 6);
1427 hash += ~(*((unsigned int*) &xyz_epsilonspace[ 2 ]) << 11);
1428 hash ^= (*((unsigned int*) &xyz_epsilonspace[ 2 ]) >> 16);
1431 //hash = hash & (HASHTABLE_SIZE-1);
1432 hash = hash % (HASHTABLE_SIZE);
1436 picoVertexCombinationHash_t **PicoNewVertexCombinationHashTable( void )
1438 picoVertexCombinationHash_t **hashTable = _pico_alloc( HASHTABLE_SIZE * sizeof(picoVertexCombinationHash_t*) );
1440 memset( hashTable, 0, HASHTABLE_SIZE * sizeof(picoVertexCombinationHash_t*) );
1445 void PicoFreeVertexCombinationHashTable( picoVertexCombinationHash_t **hashTable )
1448 picoVertexCombinationHash_t *vertexCombinationHash;
1449 picoVertexCombinationHash_t *nextVertexCombinationHash;
1452 if (hashTable == NULL)
1455 for( i = 0; i < HASHTABLE_SIZE; i++ )
1459 nextVertexCombinationHash = NULL;
1461 for( vertexCombinationHash = hashTable[ i ]; vertexCombinationHash; vertexCombinationHash = nextVertexCombinationHash )
1463 nextVertexCombinationHash = vertexCombinationHash->next;
1464 if (vertexCombinationHash->data != NULL)
1466 _pico_free( vertexCombinationHash->data );
1468 _pico_free( vertexCombinationHash );
1473 _pico_free( hashTable );
1476 picoVertexCombinationHash_t *PicoFindVertexCombinationInHashTable( picoVertexCombinationHash_t **hashTable, picoVec3_t xyz, picoVec3_t normal, picoVec3_t st, picoColor_t color )
1479 picoVertexCombinationHash_t *vertexCombinationHash;
1482 if (hashTable == NULL || xyz == NULL || normal == NULL || st == NULL || color == NULL )
1485 hash = PicoVertexCoordGenerateHash( xyz );
1487 for( vertexCombinationHash = hashTable[ hash ]; vertexCombinationHash; vertexCombinationHash = vertexCombinationHash->next )
1489 #ifndef HASH_USE_EPSILON
1491 if( (vertexCombinationHash->vcd.xyz[ 0 ] != xyz[ 0 ] || vertexCombinationHash->vcd.xyz[ 1 ] != xyz[ 1 ] || vertexCombinationHash->vcd.xyz[ 2 ] != xyz[ 2 ]) )
1495 if( (vertexCombinationHash->vcd.normal[ 0 ] != normal[ 0 ] || vertexCombinationHash->vcd.normal[ 1 ] != normal[ 1 ] || vertexCombinationHash->vcd.normal[ 2 ] != normal[ 2 ]) )
1499 if( vertexCombinationHash->vcd.st[ 0 ] != st[ 0 ] || vertexCombinationHash->vcd.st[ 1 ] != st[ 1 ] )
1503 if( ( fabs(xyz[ 0 ] - vertexCombinationHash->vcd.xyz[ 0 ]) ) > HASH_XYZ_EPSILON ||
1504 ( fabs(xyz[ 1 ] - vertexCombinationHash->vcd.xyz[ 1 ]) ) > HASH_XYZ_EPSILON ||
1505 ( fabs(xyz[ 2 ] - vertexCombinationHash->vcd.xyz[ 2 ]) ) > HASH_XYZ_EPSILON )
1509 if( ( fabs(normal[ 0 ] - vertexCombinationHash->vcd.normal[ 0 ]) ) > HASH_NORMAL_EPSILON ||
1510 ( fabs(normal[ 1 ] - vertexCombinationHash->vcd.normal[ 1 ]) ) > HASH_NORMAL_EPSILON ||
1511 ( fabs(normal[ 2 ] - vertexCombinationHash->vcd.normal[ 2 ]) ) > HASH_NORMAL_EPSILON )
1515 if( ( fabs(st[ 0 ] - vertexCombinationHash->vcd.st[ 0 ]) ) > HASH_ST_EPSILON ||
1516 ( fabs(st[ 1 ] - vertexCombinationHash->vcd.st[ 1 ]) ) > HASH_ST_EPSILON )
1521 if( *((int*) vertexCombinationHash->vcd.color) != *((int*) color) )
1525 return vertexCombinationHash;
1531 picoVertexCombinationHash_t *PicoAddVertexCombinationToHashTable( picoVertexCombinationHash_t **hashTable, picoVec3_t xyz, picoVec3_t normal, picoVec3_t st, picoColor_t color, picoIndex_t index )
1534 picoVertexCombinationHash_t *vertexCombinationHash;
1537 if (hashTable == NULL || xyz == NULL || normal == NULL || st == NULL || color == NULL )
1540 vertexCombinationHash = _pico_alloc( sizeof(picoVertexCombinationHash_t) );
1542 if (!vertexCombinationHash)
1545 hash = PicoVertexCoordGenerateHash( xyz );
1547 _pico_copy_vec( xyz, vertexCombinationHash->vcd.xyz );
1548 _pico_copy_vec( normal, vertexCombinationHash->vcd.normal );
1549 _pico_copy_vec2( st, vertexCombinationHash->vcd.st );
1550 _pico_copy_color( color, vertexCombinationHash->vcd.color );
1551 vertexCombinationHash->index = index;
1552 vertexCombinationHash->data = NULL;
1553 vertexCombinationHash->next = hashTable[ hash ];
1554 hashTable[ hash ] = vertexCombinationHash;
1556 return vertexCombinationHash;
1559 /* ----------------------------------------------------------------------------
1560 specialized routines
1561 ---------------------------------------------------------------------------- */
1564 PicoFindSurfaceVertex()
1565 finds a vertex matching the set parameters
1566 fixme: needs non-naive algorithm
1569 int PicoFindSurfaceVertexNum( picoSurface_t *surface, picoVec3_t xyz, picoVec3_t normal, int numSTs, picoVec2_t *st, int numColors, picoColor_t *color, picoIndex_t smoothingGroup)
1575 if( surface == NULL || surface->numVertexes <= 0 )
1578 /* walk vertex list */
1579 for( i = 0; i < surface->numVertexes; i++ )
1582 if( xyz != NULL && (surface->xyz[ i ][ 0 ] != xyz[ 0 ] || surface->xyz[ i ][ 1 ] != xyz[ 1 ] || surface->xyz[ i ][ 2 ] != xyz[ 2 ]) )
1586 if( normal != NULL && (surface->normal[ i ][ 0 ] != normal[ 0 ] || surface->normal[ i ][ 1 ] != normal[ 1 ] || surface->normal[ i ][ 2 ] != normal[ 2 ]) )
1590 if( surface->smoothingGroup[ i ] != smoothingGroup )
1594 if( numSTs > 0 && st != NULL )
1596 for( j = 0; j < numSTs; j++ )
1598 if( surface->st[ j ][ i ][ 0 ] != st[ j ][ 0 ] || surface->st[ j ][ i ][ 1 ] != st[ j ][ 1 ] )
1606 if( numColors > 0 && color != NULL )
1608 for( j = 0; j < numSTs; j++ )
1610 if( *((int*) surface->color[ j ]) != *((int*) color[ j ]) )
1613 if( j != numColors )
1617 /* vertex matches */
1628 typedef struct _IndexArray IndexArray;
1635 void indexarray_push_back(IndexArray* self, picoIndex_t value)
1637 *self->last++ = value;
1640 size_t indexarray_size(IndexArray* self)
1642 return self->last - self->data;
1645 void indexarray_reserve(IndexArray* self, size_t size)
1647 self->data = self->last = _pico_calloc(size, sizeof(picoIndex_t));
1650 void indexarray_clear(IndexArray* self)
1652 _pico_free(self->data);
1655 typedef struct _BinaryTreeNode BinaryTreeNode;
1656 struct _BinaryTreeNode
1662 typedef struct _BinaryTree BinaryTree;
1665 BinaryTreeNode* data;
1666 BinaryTreeNode* last;
1669 void binarytree_extend(BinaryTree* self)
1671 self->last->left = 0;
1672 self->last->right = 0;
1676 size_t binarytree_size(BinaryTree* self)
1678 return self->last - self->data;
1681 void binarytree_reserve(BinaryTree* self, size_t size)
1683 self->data = self->last = _pico_calloc(size, sizeof(BinaryTreeNode));
1686 void binarytree_clear(BinaryTree* self)
1688 _pico_free(self->data);
1691 typedef int (*LessFunc)(void*, picoIndex_t, picoIndex_t);
1693 typedef struct _UniqueIndices UniqueIndices;
1694 struct _UniqueIndices
1702 size_t UniqueIndices_size(UniqueIndices* self)
1704 return binarytree_size(&self->tree);
1707 void UniqueIndices_reserve(UniqueIndices* self, size_t size)
1709 binarytree_reserve(&self->tree, size);
1710 indexarray_reserve(&self->indices, size);
1713 void UniqueIndices_init(UniqueIndices* self, LessFunc lessFunc, void* lessData)
1715 self->lessFunc = lessFunc;
1716 self->lessData = lessData;
1719 void UniqueIndices_destroy(UniqueIndices* self)
1721 binarytree_clear(&self->tree);
1722 indexarray_clear(&self->indices);
1726 picoIndex_t UniqueIndices_find_or_insert(UniqueIndices* self, picoIndex_t value)
1728 picoIndex_t index = 0;
1732 if(self->lessFunc(self->lessData, value, self->indices.data[index]))
1734 BinaryTreeNode* node = self->tree.data + index;
1742 node->left = (picoIndex_t)binarytree_size(&self->tree);
1743 binarytree_extend(&self->tree);
1744 indexarray_push_back(&self->indices, value);
1748 if(self->lessFunc(self->lessData, self->indices.data[index], value))
1750 BinaryTreeNode* node = self->tree.data + index;
1751 if(node->right != 0)
1753 index = node->right;
1758 node->right = (picoIndex_t)binarytree_size(&self->tree);
1759 binarytree_extend(&self->tree);
1760 indexarray_push_back(&self->indices, value);
1769 picoIndex_t UniqueIndices_insert(UniqueIndices* self, picoIndex_t value)
1771 if(self->tree.data == self->tree.last)
1773 binarytree_extend(&self->tree);
1774 indexarray_push_back(&self->indices, value);
1779 return UniqueIndices_find_or_insert(self, value);
1783 typedef struct picoSmoothVertices_s picoSmoothVertices_t;
1784 struct picoSmoothVertices_s
1787 picoIndex_t* smoothingGroups;
1790 int lessSmoothVertex(void* data, picoIndex_t first, picoIndex_t second)
1792 picoSmoothVertices_t* smoothVertices = data;
1794 if(smoothVertices->xyz[first][0] != smoothVertices->xyz[second][0])
1796 return smoothVertices->xyz[first][0] < smoothVertices->xyz[second][0];
1798 if(smoothVertices->xyz[first][1] != smoothVertices->xyz[second][1])
1800 return smoothVertices->xyz[first][1] < smoothVertices->xyz[second][1];
1802 if(smoothVertices->xyz[first][2] != smoothVertices->xyz[second][2])
1804 return smoothVertices->xyz[first][2] < smoothVertices->xyz[second][2];
1806 if(smoothVertices->smoothingGroups[first] != smoothVertices->smoothingGroups[second])
1808 return smoothVertices->smoothingGroups[first] < smoothVertices->smoothingGroups[second];
1813 void _pico_vertices_combine_shared_normals(picoVec3_t* xyz, picoIndex_t* smoothingGroups, picoVec3_t* normals, picoIndex_t numVertices)
1815 UniqueIndices vertices;
1817 picoSmoothVertices_t smoothVertices = { xyz, smoothingGroups };
1818 UniqueIndices_init(&vertices, lessSmoothVertex, &smoothVertices);
1819 UniqueIndices_reserve(&vertices, numVertices);
1820 indexarray_reserve(&indices, numVertices);
1825 for(; i < numVertices; ++i)
1827 size_t size = UniqueIndices_size(&vertices);
1828 picoIndex_t index = UniqueIndices_insert(&vertices, i);
1829 if((size_t)index != size)
1831 float* normal = normals[vertices.indices.data[index]];
1832 _pico_add_vec(normal, normals[i], normal);
1834 indexarray_push_back(&indices, index);
1839 picoIndex_t maxIndex = 0;
1840 picoIndex_t* i = indices.data;
1841 for(; i != indices.last; ++i)
1845 _pico_copy_vec(normals[vertices.indices.data[*i]], normals[i - indices.data]);
1854 UniqueIndices_destroy(&vertices);
1855 indexarray_clear(&indices);
1858 typedef picoVec3_t* picoNormalIter_t;
1859 typedef picoIndex_t* picoIndexIter_t;
1861 #define THE_CROSSPRODUCTS_OF_ANY_PAIR_OF_EDGES_OF_A_GIVEN_TRIANGLE_ARE_EQUAL 1
1863 void _pico_triangles_generate_weighted_normals(picoIndexIter_t first, picoIndexIter_t end, picoVec3_t* xyz, picoVec3_t* normals)
1865 for(; first != end; first += 3)
1867 #if (THE_CROSSPRODUCTS_OF_ANY_PAIR_OF_EDGES_OF_A_GIVEN_TRIANGLE_ARE_EQUAL)
1868 picoVec3_t weightedNormal;
1870 float* a = xyz[*(first + 0)];
1871 float* b = xyz[*(first + 1)];
1872 float* c = xyz[*(first + 2)];
1874 _pico_subtract_vec( b, a, ba );
1875 _pico_subtract_vec( c, a, ca );
1876 _pico_cross_vec( ca, ba, weightedNormal );
1883 float* normal = normals[*(first + j)];
1884 #if (!THE_CROSSPRODUCTS_OF_ANY_PAIR_OF_EDGES_OF_A_GIVEN_TRIANGLE_ARE_EQUAL)
1885 picoVec3_t weightedNormal;
1887 float* a = xyz[*(first + ((j + 0) % 3))];
1888 float* b = xyz[*(first + ((j + 1) % 3))];
1889 float* c = xyz[*(first + ((j + 2) % 3))];
1891 _pico_subtract_vec( b, a, ba );
1892 _pico_subtract_vec( c, a, ca );
1893 _pico_cross_vec( ca, ba, weightedNormal );
1896 _pico_add_vec(weightedNormal, normal, normal);
1902 void _pico_normals_zero(picoNormalIter_t first, picoNormalIter_t last)
1904 for(; first != last; ++first)
1906 _pico_zero_vec(*first);
1910 void _pico_normals_normalize(picoNormalIter_t first, picoNormalIter_t last)
1912 for(; first != last; ++first)
1914 _pico_normalize_vec(*first);
1918 double _pico_length_vec( picoVec3_t vec )
1920 return sqrt( vec[ 0 ] * vec[ 0 ] + vec[ 1 ] * vec[ 1 ] + vec[ 2 ] * vec[ 2 ] );
1923 #define NORMAL_UNIT_LENGTH_EPSILON 0.01
1924 #define FLOAT_EQUAL_EPSILON(f, other, epsilon) (fabs(f - other) < epsilon)
1926 int _pico_normal_is_unit_length(picoVec3_t normal)
1928 return FLOAT_EQUAL_EPSILON(_pico_length_vec(normal), 1.0, NORMAL_UNIT_LENGTH_EPSILON);
1931 int _pico_normal_within_tolerance(picoVec3_t normal, picoVec3_t other)
1933 return _pico_dot_vec(normal, other) > 0.0f;
1937 void _pico_normals_assign_generated_normals(picoNormalIter_t first, picoNormalIter_t last, picoNormalIter_t generated)
1939 for(; first != last; ++first, ++generated)
1941 if(!_pico_normal_is_unit_length(*first) || !_pico_normal_within_tolerance(*first, *generated))
1943 _pico_copy_vec(*generated, *first);
1948 void PicoFixSurfaceNormals(picoSurface_t* surface)
1950 picoVec3_t* normals = (picoVec3_t*)_pico_calloc(surface->numVertexes, sizeof(picoVec3_t));
1952 _pico_normals_zero(normals, normals + surface->numVertexes);
1954 _pico_triangles_generate_weighted_normals(surface->index, surface->index + surface->numIndexes, surface->xyz, normals);
1955 _pico_vertices_combine_shared_normals(surface->xyz, surface->smoothingGroup, normals, surface->numVertexes);
1957 _pico_normals_normalize(normals, normals + surface->numVertexes);
1959 _pico_normals_assign_generated_normals(surface->normal, surface->normal + surface->numVertexes, normals);
1961 _pico_free(normals);
1966 PicoRemapModel() - sea
1967 remaps model material/etc. information using the remappings
1968 contained in the given 'remapFile' (full path to the ascii file to open)
1969 returns 1 on success or 0 on error
1972 #define _prm_error_return \
1974 _pico_free_parser( p ); \
1975 _pico_free_file( remapBuffer ); \
1979 int PicoRemapModel( picoModel_t *model, char *remapFile )
1982 picoByte_t *remapBuffer;
1987 if( model == NULL || remapFile == NULL )
1990 /* load remap file contents */
1991 _pico_load_file( remapFile,&remapBuffer,&remapBufSize );
1994 if( remapBufSize == 0 )
1995 return 1; /* file is empty: no error */
1996 if( remapBufSize < 0 )
1997 return 0; /* load failed: error */
1999 /* create a new pico parser */
2000 p = _pico_new_parser( remapBuffer, remapBufSize );
2003 /* ram is really cheap nowadays... */
2010 /* get next token in remap file */
2011 if (!_pico_parse( p,1 ))
2014 /* skip over c++ style comment lines */
2015 if (!_pico_stricmp(p->token,"//"))
2017 _pico_parse_skip_rest( p );
2021 /* block for quick material shader name remapping */
2022 /* materials { "m" (=>|->|=) "s" } */
2023 if( !_pico_stricmp(p->token, "materials" ) )
2028 if (!_pico_parse_check( p,1,"{" ))
2031 /* process assignments */
2034 picoShader_t *shader;
2038 /* get material name */
2039 if (_pico_parse( p,1 ) == NULL) break;
2040 if (!strlen(p->token)) continue;
2041 materialName = _pico_clone_alloc( p->token );
2042 if (materialName == NULL)
2046 if (p->token[0] == '{') level++;
2047 if (p->token[0] == '}') level--;
2050 /* get next token (assignment token or shader name) */
2051 if (!_pico_parse( p,0 ))
2053 _pico_free( materialName );
2056 /* skip assignment token (if present) */
2057 if (!strcmp(p->token,"=>") ||
2058 !strcmp(p->token,"->") ||
2059 !strcmp(p->token,"="))
2061 /* simply grab the next token */
2062 if (!_pico_parse( p,0 ))
2064 _pico_free( materialName );
2068 /* try to find material by name */
2069 shader = PicoFindShader( model,materialName,0 );
2071 /* we've found a material matching the name */
2074 PicoSetShaderName( shader,p->token );
2076 /* free memory used by material name */
2077 _pico_free( materialName );
2080 _pico_parse_skip_rest( p );
2083 /* block for detailed single material remappings */
2084 /* materials[ "m" ] { key data... } */
2085 else if (!_pico_stricmp(p->token,"materials["))
2087 picoShader_t *shader;
2088 char *tempMaterialName;
2091 /* get material name */
2092 if (!_pico_parse( p,0 ))
2095 /* temporary copy of material name */
2096 tempMaterialName = _pico_clone_alloc( p->token );
2097 if (tempMaterialName == NULL)
2100 /* check square closing bracket */
2101 if (!_pico_parse_check( p,0,"]" ))
2104 /* try to find material by name */
2105 shader = PicoFindShader( model,tempMaterialName,0 );
2107 /* free memory used by temporary material name */
2108 _pico_free( tempMaterialName );
2110 /* we haven't found a material matching the name */
2111 /* so we simply skip the braced section now and */
2112 /* continue parsing with the next main token */
2115 _pico_parse_skip_braced( p );
2118 /* check opening bracket */
2119 if (!_pico_parse_check( p,1,"{" ))
2122 /* process material info keys */
2126 if (_pico_parse( p,1 ) == NULL) break;
2127 if (!strlen(p->token)) continue;
2130 if (p->token[0] == '{') level++;
2131 if (p->token[0] == '}') level--;
2134 /* remap shader name */
2135 if (!_pico_stricmp(p->token,"shader"))
2137 if (!_pico_parse( p,0 )) _prm_error_return;
2138 PicoSetShaderName( shader,p->token );
2140 /* remap shader map name */
2141 else if (!_pico_stricmp(p->token,"mapname"))
2143 if (!_pico_parse( p,0 )) _prm_error_return;
2144 PicoSetShaderMapName( shader,p->token );
2146 /* remap shader's ambient color */
2147 else if (!_pico_stricmp(p->token,"ambient"))
2152 /* get vector from parser */
2153 if (!_pico_parse_vec( p,v )) _prm_error_return;
2155 /* store as color */
2156 color[ 0 ] = (picoByte_t)v[ 0 ];
2157 color[ 1 ] = (picoByte_t)v[ 1 ];
2158 color[ 2 ] = (picoByte_t)v[ 2 ];
2160 /* set new ambient color */
2161 PicoSetShaderAmbientColor( shader,color );
2163 /* remap shader's diffuse color */
2164 else if (!_pico_stricmp(p->token,"diffuse"))
2169 /* get vector from parser */
2170 if (!_pico_parse_vec( p,v )) _prm_error_return;
2172 /* store as color */
2173 color[ 0 ] = (picoByte_t)v[ 0 ];
2174 color[ 1 ] = (picoByte_t)v[ 1 ];
2175 color[ 2 ] = (picoByte_t)v[ 2 ];
2177 /* set new ambient color */
2178 PicoSetShaderDiffuseColor( shader,color );
2180 /* remap shader's specular color */
2181 else if (!_pico_stricmp(p->token,"specular"))
2186 /* get vector from parser */
2187 if (!_pico_parse_vec( p,v )) _prm_error_return;
2189 /* store as color */
2190 color[ 0 ] = (picoByte_t)v[ 0 ];
2191 color[ 1 ] = (picoByte_t)v[ 1 ];
2192 color[ 2 ] = (picoByte_t)v[ 2 ];
2194 /* set new ambient color */
2195 PicoSetShaderSpecularColor( shader,color );
2198 _pico_parse_skip_rest( p );
2201 /* end 'materials[' */
2204 /* free both parser and file buffer */
2205 _pico_free_parser( p );
2206 _pico_free_file( remapBuffer );
2208 /* return with success */
2214 PicoAddTriangleToModel() - jhefty
2215 A nice way to add individual triangles to the model.
2216 Chooses an appropriate surface based on the shader, or adds a new surface if necessary
2219 void PicoAddTriangleToModel( picoModel_t *model, picoVec3_t** xyz, picoVec3_t** normals,
2220 int numSTs, picoVec2_t **st, int numColors, picoColor_t **colors,
2221 picoShader_t* shader, picoIndex_t* smoothingGroup )
2225 picoSurface_t* workSurface = NULL;
2227 /* see if a surface already has the shader */
2228 for ( i = 0 ; i < model->numSurfaces ; i++ )
2230 workSurface = model->surface[i];
2231 if ( workSurface->shader == shader )
2237 /* no surface uses this shader yet, so create a new surface */
2238 if ( !workSurface || i >=model->numSurfaces )
2240 /* create a new surface in the model for the unique shader */
2241 workSurface = PicoNewSurface(model);
2244 _pico_printf ( PICO_ERROR , "Could not allocate a new surface!\n" );
2248 /* do surface setup */
2249 PicoSetSurfaceType( workSurface, PICO_TRIANGLES );
2250 PicoSetSurfaceName( workSurface, shader->name );
2251 PicoSetSurfaceShader( workSurface, shader );
2254 /* add the triangle data to the surface */
2255 for ( i = 0 ; i < 3 ; i++ )
2257 /* get the next free spot in the index array */
2258 int newVertIndex = PicoGetSurfaceNumIndexes ( workSurface );
2260 /* get the index of the vertex that we're going to store at newVertIndex */
2261 vertDataIndex = PicoFindSurfaceVertexNum ( workSurface , *xyz[i] , *normals[i] , numSTs , st[i] , numColors , colors[i], smoothingGroup[i]);
2263 /* the vertex wasn't found, so create a new vertex in the pool from the data we have */
2264 if ( vertDataIndex == -1 )
2266 /* find the next spot for a new vertex */
2267 vertDataIndex = PicoGetSurfaceNumVertexes ( workSurface );
2269 /* assign the data to it */
2270 PicoSetSurfaceXYZ ( workSurface ,vertDataIndex , *xyz[i] );
2271 PicoSetSurfaceNormal ( workSurface , vertDataIndex , *normals[i] );
2273 /* make sure to copy over all available ST's and colors for the vertex */
2274 for ( j = 0 ; j < numColors ; j++ )
2276 PicoSetSurfaceColor( workSurface , j , vertDataIndex , colors[i][j] );
2278 for ( j = 0 ; j < numSTs ; j++ )
2280 PicoSetSurfaceST ( workSurface , j , vertDataIndex , st[i][j] );
2283 PicoSetSurfaceSmoothingGroup ( workSurface , vertDataIndex , smoothingGroup[i] );
2286 /* add this vertex to the triangle */
2287 PicoSetSurfaceIndex ( workSurface , newVertIndex , vertDataIndex );