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);
308 /* ----------------------------------------------------------------------------
310 ---------------------------------------------------------------------------- */
314 creates a new pico model
317 picoModel_t *PicoNewModel( void )
322 model = _pico_alloc( sizeof(picoModel_t) );
327 memset( model,0,sizeof(picoModel_t) );
330 _pico_zero_bounds( model->mins,model->maxs );
332 /* set initial frame count to 1 -sea */
333 model->numFrames = 1;
335 /* return ptr to new model */
343 frees a model and all associated data
346 void PicoFreeModel( picoModel_t *model )
357 _pico_free( model->name );
359 if( model->fileName )
360 _pico_free( model->fileName );
363 for( i = 0; i < model->numShaders; i++ )
364 PicoFreeShader( model->shader[ i ] );
365 free( model->shader );
368 for( i = 0; i < model->numSurfaces; i++ )
369 PicoFreeSurface( model->surface[ i ] );
370 free( model->surface );
380 adjusts a models's memory allocations to handle the requested sizes.
381 will always grow, never shrink
384 int PicoAdjustModel( picoModel_t *model, int numShaders, int numSurfaces )
391 /* sea: null surface/shader fix (1s=>0s) */
394 if( numSurfaces < 0 )
397 /* additional shaders? */
398 while( numShaders > model->maxShaders )
400 model->maxShaders += PICO_GROW_SHADERS;
401 if( !_pico_realloc( (void *) &model->shader, model->numShaders * sizeof( *model->shader ), model->maxShaders * sizeof( *model->shader ) ) )
405 /* set shader count to higher */
406 if( numShaders > model->numShaders )
407 model->numShaders = numShaders;
409 /* additional surfaces? */
410 while( numSurfaces > model->maxSurfaces )
412 model->maxSurfaces += PICO_GROW_SURFACES;
413 if( !_pico_realloc( (void *) &model->surface, model->numSurfaces * sizeof( *model->surface ), model->maxSurfaces * sizeof( *model->surface ) ) )
417 /* set shader count to higher */
418 if( numSurfaces > model->numSurfaces )
419 model->numSurfaces = numSurfaces;
427 /* ----------------------------------------------------------------------------
429 ---------------------------------------------------------------------------- */
433 creates a new pico shader and returns its index. -sea
436 picoShader_t *PicoNewShader( picoModel_t *model )
438 picoShader_t *shader;
441 /* allocate and clear */
442 shader = _pico_alloc( sizeof(picoShader_t) );
445 memset( shader, 0, sizeof(picoShader_t) );
447 /* attach it to the model */
451 if( !PicoAdjustModel( model, model->numShaders + 1, 0 ) )
453 _pico_free( shader );
458 model->shader[ model->numShaders - 1 ] = shader;
459 shader->model = model;
462 /* setup default shader colors */
463 _pico_set_color( shader->ambientColor,0,0,0,0 );
464 _pico_set_color( shader->diffuseColor,255,255,255,1 );
465 _pico_set_color( shader->specularColor,0,0,0,0 );
467 /* no need to do this, but i do it anyway */
468 shader->transparency = 0;
469 shader->shininess = 0;
471 /* return the newly created shader */
479 frees a shader and all associated data -sea
482 void PicoFreeShader( picoShader_t *shader )
490 _pico_free( shader->name );
491 if( shader->mapName )
492 _pico_free( shader->mapName );
494 /* free the shader */
495 _pico_free( shader );
502 finds a named shader in a model
505 picoShader_t *PicoFindShader( picoModel_t *model, char *name, int caseSensitive )
511 if( model == NULL || name == NULL ) /* sea: null name fix */
515 for( i = 0; i < model->numShaders; i++ )
517 /* skip null shaders or shaders with null names */
518 if( model->shader[ i ] == NULL ||
519 model->shader[ i ]->name == NULL )
522 /* compare the shader name with name we're looking for */
525 if( !strcmp( name, model->shader[ i ]->name ) )
526 return model->shader[ i ];
528 else if( !_pico_stricmp( name, model->shader[ i ]->name ) )
529 return model->shader[ i ];
532 /* named shader not found */
538 /* ----------------------------------------------------------------------------
540 ---------------------------------------------------------------------------- */
544 creates a new pico surface
547 picoSurface_t *PicoNewSurface( picoModel_t *model )
549 picoSurface_t *surface;
550 char surfaceName[64];
552 /* allocate and clear */
553 surface = _pico_alloc( sizeof( *surface ) );
554 if( surface == NULL )
556 memset( surface, 0, sizeof( *surface ) );
558 /* attach it to the model */
562 if( !PicoAdjustModel( model, 0, model->numSurfaces + 1 ) )
564 _pico_free( surface );
569 model->surface[ model->numSurfaces - 1 ] = surface;
570 surface->model = model;
572 /* set default name */
573 sprintf( surfaceName, "Unnamed_%d", model->numSurfaces );
574 PicoSetSurfaceName( surface, surfaceName );
585 frees a surface and all associated data
587 void PicoFreeSurface( picoSurface_t *surface )
593 if( surface == NULL )
597 _pico_free( surface->xyz );
598 _pico_free( surface->normal );
599 _pico_free( surface->smoothingGroup );
600 _pico_free( surface->index );
601 _pico_free( surface->faceNormal );
604 _pico_free( surface->name );
607 for( i = 0; i < surface->numSTArrays; i++ )
608 _pico_free( surface->st[ i ] );
610 for( i = 0; i < surface->numColorArrays; i++ )
611 _pico_free( surface->color[ i ] );
612 free( surface->color );
614 /* free the surface */
615 _pico_free( surface );
622 adjusts a surface's memory allocations to handle the requested sizes.
623 will always grow, never shrink
626 int PicoAdjustSurface( picoSurface_t *surface, int numVertexes, int numSTArrays, int numColorArrays, int numIndexes, int numFaceNormals )
632 if( surface == NULL )
636 if( numVertexes < 1 )
638 if( numSTArrays < 1 )
640 if( numColorArrays < 1 )
645 /* additional vertexes? */
646 while( numVertexes > surface->maxVertexes ) /* fix */
648 surface->maxVertexes += PICO_GROW_VERTEXES;
649 if( !_pico_realloc( (void *) &surface->xyz, surface->numVertexes * sizeof( *surface->xyz ), surface->maxVertexes * sizeof( *surface->xyz ) ) )
651 if( !_pico_realloc( (void *) &surface->normal, surface->numVertexes * sizeof( *surface->normal ), surface->maxVertexes * sizeof( *surface->normal ) ) )
653 if( !_pico_realloc( (void *) &surface->smoothingGroup, surface->numVertexes * sizeof( *surface->smoothingGroup ), surface->maxVertexes * sizeof( *surface->smoothingGroup ) ) )
655 for( i = 0; i < surface->numSTArrays; i++ )
656 if( !_pico_realloc( (void*) &surface->st[ i ], surface->numVertexes * sizeof( *surface->st[ i ] ), surface->maxVertexes * sizeof( *surface->st[ i ] ) ) )
658 for( i = 0; i < surface->numColorArrays; i++ )
659 if( !_pico_realloc( (void*) &surface->color[ i ], surface->numVertexes * sizeof( *surface->color[ i ] ), surface->maxVertexes * sizeof( *surface->color[ i ] ) ) )
663 /* set vertex count to higher */
664 if( numVertexes > surface->numVertexes )
665 surface->numVertexes = numVertexes;
667 /* additional st arrays? */
668 while( numSTArrays > surface->maxSTArrays ) /* fix */
670 surface->maxSTArrays += PICO_GROW_ARRAYS;
671 if( !_pico_realloc( (void*) &surface->st, surface->numSTArrays * sizeof( *surface->st ), surface->maxSTArrays * sizeof( *surface->st ) ) )
673 while( surface->numSTArrays < numSTArrays )
675 surface->st[ surface->numSTArrays ] = _pico_alloc( surface->maxVertexes * sizeof( *surface->st[ 0 ] ) );
676 memset( surface->st[ surface->numSTArrays ], 0, surface->maxVertexes * sizeof( *surface->st[ 0 ] ) );
677 surface->numSTArrays++;
681 /* additional color arrays? */
682 while( numColorArrays > surface->maxColorArrays ) /* fix */
684 surface->maxColorArrays += PICO_GROW_ARRAYS;
685 if( !_pico_realloc( (void*) &surface->color, surface->numColorArrays * sizeof( *surface->color ), surface->maxColorArrays * sizeof( *surface->color ) ) )
687 while( surface->numColorArrays < numColorArrays )
689 surface->color[ surface->numColorArrays ] = _pico_alloc( surface->maxVertexes * sizeof( *surface->color[ 0 ] ) );
690 memset( surface->color[ surface->numColorArrays ], 0, surface->maxVertexes * sizeof( *surface->color[ 0 ] ) );
691 surface->numColorArrays++;
695 /* additional indexes? */
696 while( numIndexes > surface->maxIndexes ) /* fix */
698 surface->maxIndexes += PICO_GROW_INDEXES;
699 if( !_pico_realloc( (void*) &surface->index, surface->numIndexes * sizeof( *surface->index ), surface->maxIndexes * sizeof( *surface->index ) ) )
703 /* set index count to higher */
704 if( numIndexes > surface->numIndexes )
705 surface->numIndexes = numIndexes;
707 /* additional face normals? */
708 while( numFaceNormals > surface->maxFaceNormals ) /* fix */
710 surface->maxFaceNormals += PICO_GROW_FACES;
711 if( !_pico_realloc( (void *) &surface->faceNormal, surface->numFaceNormals * sizeof( *surface->faceNormal ), surface->maxFaceNormals * sizeof( *surface->faceNormal ) ) )
715 /* set face normal count to higher */
716 if( numFaceNormals > surface->numFaceNormals )
717 surface->numFaceNormals = numFaceNormals;
725 * Finds first matching named surface in a model.
727 picoSurface_t *PicoFindSurface(
728 picoModel_t *model, char *name, int caseSensitive )
733 if( model == NULL || name == NULL )
737 for( i = 0; i < model->numSurfaces; i++ )
739 /* skip null surfaces or surfaces with null names */
740 if( model->surface[ i ] == NULL ||
741 model->surface[ i ]->name == NULL )
744 /* compare the surface name with name we're looking for */
746 if( !strcmp(name,model->surface[ i ]->name) )
747 return model->surface[ i ];
749 if( !_pico_stricmp(name,model->surface[ i ]->name) )
750 return model->surface[ i ];
753 /* named surface not found */
759 /*----------------------------------------------------------------------------
760 PicoSet*() Setter Functions
761 ----------------------------------------------------------------------------*/
763 void PicoSetModelName( picoModel_t *model, char *name )
765 if( model == NULL || name == NULL )
767 if( model->name != NULL )
768 _pico_free( model->name );
770 model->name = _pico_clone_alloc( name );
775 void PicoSetModelFileName( picoModel_t *model, char *fileName )
777 if( model == NULL || fileName == NULL )
779 if( model->fileName != NULL )
780 _pico_free( model->fileName );
782 model->fileName = _pico_clone_alloc( fileName );
787 void PicoSetModelFrameNum( picoModel_t *model, int frameNum )
791 model->frameNum = frameNum;
796 void PicoSetModelNumFrames( picoModel_t *model, int numFrames )
800 model->numFrames = numFrames;
805 void PicoSetModelData( picoModel_t *model, void *data )
814 void PicoSetShaderName( picoShader_t *shader, char *name )
816 if( shader == NULL || name == NULL )
818 if( shader->name != NULL )
819 _pico_free( shader->name );
821 shader->name = _pico_clone_alloc( name );
826 void PicoSetShaderMapName( picoShader_t *shader, char *mapName )
828 if( shader == NULL || mapName == NULL )
830 if( shader->mapName != NULL )
831 _pico_free( shader->mapName );
833 shader->mapName = _pico_clone_alloc( mapName );
838 void PicoSetShaderAmbientColor( picoShader_t *shader, picoColor_t color )
840 if( shader == NULL || color == NULL )
842 shader->ambientColor[ 0 ] = color[ 0 ];
843 shader->ambientColor[ 1 ] = color[ 1 ];
844 shader->ambientColor[ 2 ] = color[ 2 ];
845 shader->ambientColor[ 3 ] = color[ 3 ];
850 void PicoSetShaderDiffuseColor( picoShader_t *shader, picoColor_t color )
852 if( shader == NULL || color == NULL )
854 shader->diffuseColor[ 0 ] = color[ 0 ];
855 shader->diffuseColor[ 1 ] = color[ 1 ];
856 shader->diffuseColor[ 2 ] = color[ 2 ];
857 shader->diffuseColor[ 3 ] = color[ 3 ];
862 void PicoSetShaderSpecularColor( picoShader_t *shader, picoColor_t color )
864 if( shader == NULL || color == NULL )
866 shader->specularColor[ 0 ] = color[ 0 ];
867 shader->specularColor[ 1 ] = color[ 1 ];
868 shader->specularColor[ 2 ] = color[ 2 ];
869 shader->specularColor[ 3 ] = color[ 3 ];
874 void PicoSetShaderTransparency( picoShader_t *shader, float value )
878 shader->transparency = value;
880 /* cap to 0..1 range */
881 if (shader->transparency < 0.0)
882 shader->transparency = 0.0;
883 if (shader->transparency > 1.0)
884 shader->transparency = 1.0;
889 void PicoSetShaderShininess( picoShader_t *shader, float value )
893 shader->shininess = value;
895 /* cap to 0..127 range */
896 if (shader->shininess < 0.0)
897 shader->shininess = 0.0;
898 if (shader->shininess > 127.0)
899 shader->shininess = 127.0;
904 void PicoSetSurfaceData( picoSurface_t *surface, void *data )
906 if( surface == NULL )
908 surface->data = data;
913 void PicoSetSurfaceType( picoSurface_t *surface, picoSurfaceType_t type )
915 if( surface == NULL )
917 surface->type = type;
922 void PicoSetSurfaceName( picoSurface_t *surface, char *name )
924 if( surface == NULL || name == NULL )
926 if( surface->name != NULL )
927 _pico_free( surface->name );
929 surface->name = _pico_clone_alloc( name );
934 void PicoSetSurfaceShader( picoSurface_t *surface, picoShader_t *shader )
936 if( surface == NULL )
938 surface->shader = shader;
943 void PicoSetSurfaceXYZ( picoSurface_t *surface, int num, picoVec3_t xyz )
945 if( surface == NULL || num < 0 || xyz == NULL )
947 if( !PicoAdjustSurface( surface, num + 1, 0, 0, 0, 0 ) )
949 _pico_copy_vec( xyz, surface->xyz[ num ] );
950 if( surface->model != NULL )
951 _pico_expand_bounds( xyz, surface->model->mins, surface->model->maxs );
956 void PicoSetSurfaceNormal( picoSurface_t *surface, int num, picoVec3_t normal )
958 if( surface == NULL || num < 0 || normal == NULL )
960 if( !PicoAdjustSurface( surface, num + 1, 0, 0, 0, 0 ) )
962 _pico_copy_vec( normal, surface->normal[ num ] );
967 void PicoSetSurfaceST( picoSurface_t *surface, int array, int num, picoVec2_t st )
969 if( surface == NULL || num < 0 || st == NULL )
971 if( !PicoAdjustSurface( surface, num + 1, array + 1, 0, 0, 0 ) )
973 surface->st[ array ][ num ][ 0 ] = st[ 0 ];
974 surface->st[ array ][ num ][ 1 ] = st[ 1 ];
979 void PicoSetSurfaceColor( picoSurface_t *surface, int array, int num, picoColor_t color )
981 if( surface == NULL || num < 0 || color == NULL )
983 if( !PicoAdjustSurface( surface, num + 1, 0, array + 1, 0, 0 ) )
985 surface->color[ array ][ num ][ 0 ] = color[ 0 ];
986 surface->color[ array ][ num ][ 1 ] = color[ 1 ];
987 surface->color[ array ][ num ][ 2 ] = color[ 2 ];
988 surface->color[ array ][ num ][ 3 ] = color[ 3 ];
993 void PicoSetSurfaceIndex( picoSurface_t *surface, int num, picoIndex_t index )
995 if( surface == NULL || num < 0 )
997 if( !PicoAdjustSurface( surface, 0, 0, 0, num + 1, 0 ) )
999 surface->index[ num ] = index;
1004 void PicoSetSurfaceIndexes( picoSurface_t *surface, int num, picoIndex_t *index, int count )
1006 if( num < 0 || index == NULL || count < 1 )
1008 if( !PicoAdjustSurface( surface, 0, 0, 0, num + count, 0 ) )
1010 memcpy( &surface->index[ num ], index, count * sizeof( surface->index[ num ] ) );
1015 void PicoSetFaceNormal( picoSurface_t *surface, int num, picoVec3_t normal )
1017 if( surface == NULL || num < 0 || normal == NULL )
1019 if( !PicoAdjustSurface( surface, 0, 0, 0, 0, num + 1 ) )
1021 _pico_copy_vec( normal, surface->faceNormal[ num ] );
1025 void PicoSetSurfaceSmoothingGroup( picoSurface_t *surface, int num, picoIndex_t smoothingGroup )
1029 if( !PicoAdjustSurface( surface, num + 1, 0, 0, 0, 0 ) )
1031 surface->smoothingGroup[ num ] = smoothingGroup;
1035 void PicoSetSurfaceSpecial( picoSurface_t *surface, int num, int special )
1037 if( surface == NULL || num < 0 || num >= PICO_MAX_SPECIAL )
1039 surface->special[ num ] = special;
1044 /*----------------------------------------------------------------------------
1045 PicoGet*() Getter Functions
1046 ----------------------------------------------------------------------------*/
1048 char *PicoGetModelName( picoModel_t *model )
1052 if( model->name == NULL)
1059 char *PicoGetModelFileName( picoModel_t *model )
1063 if( model->fileName == NULL)
1065 return model->fileName;
1070 int PicoGetModelFrameNum( picoModel_t *model )
1074 return model->frameNum;
1079 int PicoGetModelNumFrames( picoModel_t *model )
1083 return model->numFrames;
1088 void *PicoGetModelData( picoModel_t *model )
1097 int PicoGetModelNumShaders( picoModel_t *model )
1101 return model->numShaders;
1106 picoShader_t *PicoGetModelShader( picoModel_t *model, int num )
1108 /* a few sanity checks */
1111 if( model->shader == NULL)
1113 if( num < 0 || num >= model->numShaders )
1116 /* return the shader */
1117 return model->shader[ num ];
1122 int PicoGetModelNumSurfaces( picoModel_t *model )
1126 return model->numSurfaces;
1131 picoSurface_t *PicoGetModelSurface( picoModel_t *model, int num )
1133 /* a few sanity checks */
1136 if( model->surface == NULL)
1138 if( num < 0 || num >= model->numSurfaces )
1141 /* return the surface */
1142 return model->surface[ num ];
1147 int PicoGetModelTotalVertexes( picoModel_t *model )
1154 if( model->surface == NULL )
1158 for( i = 0; i < model->numSurfaces; i++ )
1159 count += PicoGetSurfaceNumVertexes( model->surface[ i ] );
1166 int PicoGetModelTotalIndexes( picoModel_t *model )
1173 if( model->surface == NULL )
1177 for( i = 0; i < model->numSurfaces; i++ )
1178 count += PicoGetSurfaceNumIndexes( model->surface[ i ] );
1185 char *PicoGetShaderName( picoShader_t *shader )
1187 if( shader == NULL )
1189 if( shader->name == NULL)
1191 return shader->name;
1196 char *PicoGetShaderMapName( picoShader_t *shader )
1198 if( shader == NULL )
1200 if( shader->mapName == NULL)
1202 return shader->mapName;
1207 picoByte_t *PicoGetShaderAmbientColor( picoShader_t *shader )
1209 if( shader == NULL )
1211 return shader->ambientColor;
1216 picoByte_t *PicoGetShaderDiffuseColor( picoShader_t *shader )
1218 if( shader == NULL )
1220 return shader->diffuseColor;
1225 picoByte_t *PicoGetShaderSpecularColor( picoShader_t *shader )
1227 if( shader == NULL )
1229 return shader->specularColor;
1234 float PicoGetShaderTransparency( picoShader_t *shader )
1236 if( shader == NULL )
1238 return shader->transparency;
1243 float PicoGetShaderShininess( picoShader_t *shader )
1245 if( shader == NULL )
1247 return shader->shininess;
1252 void *PicoGetSurfaceData( picoSurface_t *surface )
1254 if( surface == NULL )
1256 return surface->data;
1261 picoSurfaceType_t PicoGetSurfaceType( picoSurface_t *surface )
1263 if( surface == NULL )
1265 return surface->type;
1270 char *PicoGetSurfaceName( picoSurface_t *surface )
1272 if( surface == NULL )
1274 if( surface->name == NULL )
1276 return surface->name;
1281 picoShader_t *PicoGetSurfaceShader( picoSurface_t *surface )
1283 if( surface == NULL )
1285 return surface->shader;
1290 int PicoGetSurfaceNumVertexes( picoSurface_t *surface )
1292 if( surface == NULL )
1294 return surface->numVertexes;
1299 picoVec_t *PicoGetSurfaceXYZ( picoSurface_t *surface, int num )
1301 if( surface == NULL || num < 0 || num > surface->numVertexes )
1303 return surface->xyz[ num ];
1308 picoVec_t *PicoGetSurfaceNormal( picoSurface_t *surface, int num )
1310 if( surface == NULL || num < 0 || num > surface->numVertexes )
1312 return surface->normal[ num ];
1317 picoVec_t *PicoGetSurfaceST( picoSurface_t *surface, int array, int num )
1319 if( surface == NULL || array < 0 || array > surface->numSTArrays || num < 0 || num > surface->numVertexes )
1321 return surface->st[ array ][ num ];
1326 picoByte_t *PicoGetSurfaceColor( picoSurface_t *surface, int array, int num )
1328 if( surface == NULL || array < 0 || array > surface->numColorArrays || num < 0 || num > surface->numVertexes )
1330 return surface->color[ array ][ num ];
1335 int PicoGetSurfaceNumIndexes( picoSurface_t *surface )
1337 if( surface == NULL )
1339 return surface->numIndexes;
1344 picoIndex_t PicoGetSurfaceIndex( picoSurface_t *surface, int num )
1346 if( surface == NULL || num < 0 || num > surface->numIndexes )
1348 return surface->index[ num ];
1353 picoIndex_t *PicoGetSurfaceIndexes( picoSurface_t *surface, int num )
1355 if( surface == NULL || num < 0 || num > surface->numIndexes )
1357 return &surface->index[ num ];
1361 picoVec_t *PicoGetFaceNormal( picoSurface_t *surface, int num )
1363 if( surface == NULL || num < 0 || num > surface->numFaceNormals )
1365 return surface->faceNormal[ num ];
1368 picoIndex_t PicoGetSurfaceSmoothingGroup( picoSurface_t *surface, int num )
1370 if( surface == NULL || num < 0 || num > surface->numVertexes )
1372 return surface->smoothingGroup[ num ];
1376 int PicoGetSurfaceSpecial( picoSurface_t *surface, int num )
1378 if( surface == NULL || num < 0 || num >= PICO_MAX_SPECIAL )
1380 return surface->special[ num ];
1385 /* ----------------------------------------------------------------------------
1386 hashtable related functions
1387 ---------------------------------------------------------------------------- */
1389 /* hashtable code for faster vertex lookups */
1390 //#define HASHTABLE_SIZE 32768 // 2048 /* power of 2, use & */
1391 #define HASHTABLE_SIZE 7919 // 32749 // 2039 /* prime, use % */
1393 int PicoGetHashTableSize( void )
1395 return HASHTABLE_SIZE;
1398 #define HASH_USE_EPSILON
1400 #ifdef HASH_USE_EPSILON
1401 #define HASH_XYZ_EPSILON 0.01f
1402 #define HASH_XYZ_EPSILONSPACE_MULTIPLIER 1.f / HASH_XYZ_EPSILON
1403 #define HASH_ST_EPSILON 0.0001f
1404 #define HASH_NORMAL_EPSILON 0.02f
1407 unsigned int PicoVertexCoordGenerateHash( picoVec3_t xyz )
1409 unsigned int hash = 0;
1411 #ifndef HASH_USE_EPSILON
1412 hash += ~(*((unsigned int*) &xyz[ 0 ]) << 15);
1413 hash ^= (*((unsigned int*) &xyz[ 0 ]) >> 10);
1414 hash += (*((unsigned int*) &xyz[ 1 ]) << 3);
1415 hash ^= (*((unsigned int*) &xyz[ 1 ]) >> 6);
1416 hash += ~(*((unsigned int*) &xyz[ 2 ]) << 11);
1417 hash ^= (*((unsigned int*) &xyz[ 2 ]) >> 16);
1419 picoVec3_t xyz_epsilonspace;
1421 _pico_scale_vec( xyz, HASH_XYZ_EPSILONSPACE_MULTIPLIER, xyz_epsilonspace );
1422 xyz_epsilonspace[ 0 ] = (float)floor(xyz_epsilonspace[ 0 ]);
1423 xyz_epsilonspace[ 1 ] = (float)floor(xyz_epsilonspace[ 1 ]);
1424 xyz_epsilonspace[ 2 ] = (float)floor(xyz_epsilonspace[ 2 ]);
1426 hash += ~(*((unsigned int*) &xyz_epsilonspace[ 0 ]) << 15);
1427 hash ^= (*((unsigned int*) &xyz_epsilonspace[ 0 ]) >> 10);
1428 hash += (*((unsigned int*) &xyz_epsilonspace[ 1 ]) << 3);
1429 hash ^= (*((unsigned int*) &xyz_epsilonspace[ 1 ]) >> 6);
1430 hash += ~(*((unsigned int*) &xyz_epsilonspace[ 2 ]) << 11);
1431 hash ^= (*((unsigned int*) &xyz_epsilonspace[ 2 ]) >> 16);
1434 //hash = hash & (HASHTABLE_SIZE-1);
1435 hash = hash % (HASHTABLE_SIZE);
1439 picoVertexCombinationHash_t **PicoNewVertexCombinationHashTable( void )
1441 picoVertexCombinationHash_t **hashTable = _pico_alloc( HASHTABLE_SIZE * sizeof(picoVertexCombinationHash_t*) );
1443 memset( hashTable, 0, HASHTABLE_SIZE * sizeof(picoVertexCombinationHash_t*) );
1448 void PicoFreeVertexCombinationHashTable( picoVertexCombinationHash_t **hashTable )
1451 picoVertexCombinationHash_t *vertexCombinationHash;
1452 picoVertexCombinationHash_t *nextVertexCombinationHash;
1455 if (hashTable == NULL)
1458 for( i = 0; i < HASHTABLE_SIZE; i++ )
1462 nextVertexCombinationHash = NULL;
1464 for( vertexCombinationHash = hashTable[ i ]; vertexCombinationHash; vertexCombinationHash = nextVertexCombinationHash )
1466 nextVertexCombinationHash = vertexCombinationHash->next;
1467 if (vertexCombinationHash->data != NULL)
1469 _pico_free( vertexCombinationHash->data );
1471 _pico_free( vertexCombinationHash );
1476 _pico_free( hashTable );
1479 picoVertexCombinationHash_t *PicoFindVertexCombinationInHashTable( picoVertexCombinationHash_t **hashTable, picoVec3_t xyz, picoVec3_t normal, picoVec3_t st, picoColor_t color )
1482 picoVertexCombinationHash_t *vertexCombinationHash;
1485 if (hashTable == NULL || xyz == NULL || normal == NULL || st == NULL || color == NULL )
1488 hash = PicoVertexCoordGenerateHash( xyz );
1490 for( vertexCombinationHash = hashTable[ hash ]; vertexCombinationHash; vertexCombinationHash = vertexCombinationHash->next )
1492 #ifndef HASH_USE_EPSILON
1494 if( (vertexCombinationHash->vcd.xyz[ 0 ] != xyz[ 0 ] || vertexCombinationHash->vcd.xyz[ 1 ] != xyz[ 1 ] || vertexCombinationHash->vcd.xyz[ 2 ] != xyz[ 2 ]) )
1498 if( (vertexCombinationHash->vcd.normal[ 0 ] != normal[ 0 ] || vertexCombinationHash->vcd.normal[ 1 ] != normal[ 1 ] || vertexCombinationHash->vcd.normal[ 2 ] != normal[ 2 ]) )
1502 if( vertexCombinationHash->vcd.st[ 0 ] != st[ 0 ] || vertexCombinationHash->vcd.st[ 1 ] != st[ 1 ] )
1506 if( ( fabs(xyz[ 0 ] - vertexCombinationHash->vcd.xyz[ 0 ]) ) > HASH_XYZ_EPSILON ||
1507 ( fabs(xyz[ 1 ] - vertexCombinationHash->vcd.xyz[ 1 ]) ) > HASH_XYZ_EPSILON ||
1508 ( fabs(xyz[ 2 ] - vertexCombinationHash->vcd.xyz[ 2 ]) ) > HASH_XYZ_EPSILON )
1512 if( ( fabs(normal[ 0 ] - vertexCombinationHash->vcd.normal[ 0 ]) ) > HASH_NORMAL_EPSILON ||
1513 ( fabs(normal[ 1 ] - vertexCombinationHash->vcd.normal[ 1 ]) ) > HASH_NORMAL_EPSILON ||
1514 ( fabs(normal[ 2 ] - vertexCombinationHash->vcd.normal[ 2 ]) ) > HASH_NORMAL_EPSILON )
1518 if( ( fabs(st[ 0 ] - vertexCombinationHash->vcd.st[ 0 ]) ) > HASH_ST_EPSILON ||
1519 ( fabs(st[ 1 ] - vertexCombinationHash->vcd.st[ 1 ]) ) > HASH_ST_EPSILON )
1524 if( *((int*) vertexCombinationHash->vcd.color) != *((int*) color) )
1528 return vertexCombinationHash;
1534 picoVertexCombinationHash_t *PicoAddVertexCombinationToHashTable( picoVertexCombinationHash_t **hashTable, picoVec3_t xyz, picoVec3_t normal, picoVec3_t st, picoColor_t color, picoIndex_t index )
1537 picoVertexCombinationHash_t *vertexCombinationHash;
1540 if (hashTable == NULL || xyz == NULL || normal == NULL || st == NULL || color == NULL )
1543 vertexCombinationHash = _pico_alloc( sizeof(picoVertexCombinationHash_t) );
1545 if (!vertexCombinationHash)
1548 hash = PicoVertexCoordGenerateHash( xyz );
1550 _pico_copy_vec( xyz, vertexCombinationHash->vcd.xyz );
1551 _pico_copy_vec( normal, vertexCombinationHash->vcd.normal );
1552 _pico_copy_vec2( st, vertexCombinationHash->vcd.st );
1553 _pico_copy_color( color, vertexCombinationHash->vcd.color );
1554 vertexCombinationHash->index = index;
1555 vertexCombinationHash->data = NULL;
1556 vertexCombinationHash->next = hashTable[ hash ];
1557 hashTable[ hash ] = vertexCombinationHash;
1559 return vertexCombinationHash;
1562 /* ----------------------------------------------------------------------------
1563 specialized routines
1564 ---------------------------------------------------------------------------- */
1567 PicoFindSurfaceVertex()
1568 finds a vertex matching the set parameters
1569 fixme: needs non-naive algorithm
1572 int PicoFindSurfaceVertexNum( picoSurface_t *surface, picoVec3_t xyz, picoVec3_t normal, int numSTs, picoVec2_t *st, int numColors, picoColor_t *color, picoIndex_t smoothingGroup)
1578 if( surface == NULL || surface->numVertexes <= 0 )
1581 /* walk vertex list */
1582 for( i = 0; i < surface->numVertexes; i++ )
1585 if( xyz != NULL && (surface->xyz[ i ][ 0 ] != xyz[ 0 ] || surface->xyz[ i ][ 1 ] != xyz[ 1 ] || surface->xyz[ i ][ 2 ] != xyz[ 2 ]) )
1589 if( normal != NULL && (surface->normal[ i ][ 0 ] != normal[ 0 ] || surface->normal[ i ][ 1 ] != normal[ 1 ] || surface->normal[ i ][ 2 ] != normal[ 2 ]) )
1593 if( surface->smoothingGroup[ i ] != smoothingGroup )
1597 if( numSTs > 0 && st != NULL )
1599 for( j = 0; j < numSTs; j++ )
1601 if( surface->st[ j ][ i ][ 0 ] != st[ j ][ 0 ] || surface->st[ j ][ i ][ 1 ] != st[ j ][ 1 ] )
1609 if( numColors > 0 && color != NULL )
1611 for( j = 0; j < numSTs; j++ )
1613 if( *((int*) surface->color[ j ]) != *((int*) color[ j ]) )
1616 if( j != numColors )
1620 /* vertex matches */
1631 typedef struct _IndexArray IndexArray;
1638 void indexarray_push_back(IndexArray* self, picoIndex_t value)
1640 *self->last++ = value;
1643 size_t indexarray_size(IndexArray* self)
1645 return self->last - self->data;
1648 void indexarray_reserve(IndexArray* self, size_t size)
1650 self->data = self->last = _pico_calloc(size, sizeof(picoIndex_t));
1653 void indexarray_clear(IndexArray* self)
1655 _pico_free(self->data);
1658 typedef struct _BinaryTreeNode BinaryTreeNode;
1659 struct _BinaryTreeNode
1665 typedef struct _BinaryTree BinaryTree;
1668 BinaryTreeNode* data;
1669 BinaryTreeNode* last;
1672 void binarytree_extend(BinaryTree* self)
1674 self->last->left = 0;
1675 self->last->right = 0;
1679 size_t binarytree_size(BinaryTree* self)
1681 return self->last - self->data;
1684 void binarytree_reserve(BinaryTree* self, size_t size)
1686 self->data = self->last = _pico_calloc(size, sizeof(BinaryTreeNode));
1689 void binarytree_clear(BinaryTree* self)
1691 _pico_free(self->data);
1694 typedef int (*LessFunc)(void*, picoIndex_t, picoIndex_t);
1696 typedef struct _UniqueIndices UniqueIndices;
1697 struct _UniqueIndices
1705 size_t UniqueIndices_size(UniqueIndices* self)
1707 return binarytree_size(&self->tree);
1710 void UniqueIndices_reserve(UniqueIndices* self, size_t size)
1712 binarytree_reserve(&self->tree, size);
1713 indexarray_reserve(&self->indices, size);
1716 void UniqueIndices_init(UniqueIndices* self, LessFunc lessFunc, void* lessData)
1718 self->lessFunc = lessFunc;
1719 self->lessData = lessData;
1722 void UniqueIndices_destroy(UniqueIndices* self)
1724 binarytree_clear(&self->tree);
1725 indexarray_clear(&self->indices);
1729 picoIndex_t UniqueIndices_find_or_insert(UniqueIndices* self, picoIndex_t value)
1731 picoIndex_t index = 0;
1735 if(self->lessFunc(self->lessData, value, self->indices.data[index]))
1737 BinaryTreeNode* node = self->tree.data + index;
1745 node->left = (picoIndex_t)binarytree_size(&self->tree);
1746 binarytree_extend(&self->tree);
1747 indexarray_push_back(&self->indices, value);
1751 if(self->lessFunc(self->lessData, self->indices.data[index], value))
1753 BinaryTreeNode* node = self->tree.data + index;
1754 if(node->right != 0)
1756 index = node->right;
1761 node->right = (picoIndex_t)binarytree_size(&self->tree);
1762 binarytree_extend(&self->tree);
1763 indexarray_push_back(&self->indices, value);
1772 picoIndex_t UniqueIndices_insert(UniqueIndices* self, picoIndex_t value)
1774 if(self->tree.data == self->tree.last)
1776 binarytree_extend(&self->tree);
1777 indexarray_push_back(&self->indices, value);
1782 return UniqueIndices_find_or_insert(self, value);
1786 typedef struct picoSmoothVertices_s picoSmoothVertices_t;
1787 struct picoSmoothVertices_s
1790 picoIndex_t* smoothingGroups;
1793 int lessSmoothVertex(void* data, picoIndex_t first, picoIndex_t second)
1795 picoSmoothVertices_t* smoothVertices = data;
1797 if(smoothVertices->xyz[first][0] != smoothVertices->xyz[second][0])
1799 return smoothVertices->xyz[first][0] < smoothVertices->xyz[second][0];
1801 if(smoothVertices->xyz[first][1] != smoothVertices->xyz[second][1])
1803 return smoothVertices->xyz[first][1] < smoothVertices->xyz[second][1];
1805 if(smoothVertices->xyz[first][2] != smoothVertices->xyz[second][2])
1807 return smoothVertices->xyz[first][2] < smoothVertices->xyz[second][2];
1809 if(smoothVertices->smoothingGroups[first] != smoothVertices->smoothingGroups[second])
1811 return smoothVertices->smoothingGroups[first] < smoothVertices->smoothingGroups[second];
1816 void _pico_vertices_combine_shared_normals(picoVec3_t* xyz, picoIndex_t* smoothingGroups, picoVec3_t* normals, picoIndex_t numVertices)
1818 UniqueIndices vertices;
1820 picoSmoothVertices_t smoothVertices = { xyz, smoothingGroups };
1821 UniqueIndices_init(&vertices, lessSmoothVertex, &smoothVertices);
1822 UniqueIndices_reserve(&vertices, numVertices);
1823 indexarray_reserve(&indices, numVertices);
1828 for(; i < numVertices; ++i)
1830 size_t size = UniqueIndices_size(&vertices);
1831 picoIndex_t index = UniqueIndices_insert(&vertices, i);
1832 if((size_t)index != size)
1834 float* normal = normals[vertices.indices.data[index]];
1835 _pico_add_vec(normal, normals[i], normal);
1837 indexarray_push_back(&indices, index);
1842 picoIndex_t maxIndex = 0;
1843 picoIndex_t* i = indices.data;
1844 for(; i != indices.last; ++i)
1848 _pico_copy_vec(normals[vertices.indices.data[*i]], normals[i - indices.data]);
1857 UniqueIndices_destroy(&vertices);
1858 indexarray_clear(&indices);
1861 typedef picoVec3_t* picoNormalIter_t;
1862 typedef picoIndex_t* picoIndexIter_t;
1864 #define THE_CROSSPRODUCTS_OF_ANY_PAIR_OF_EDGES_OF_A_GIVEN_TRIANGLE_ARE_EQUAL 1
1866 void _pico_triangles_generate_weighted_normals(picoIndexIter_t first, picoIndexIter_t end, picoVec3_t* xyz, picoVec3_t* normals)
1868 for(; first != end; first += 3)
1870 #if (THE_CROSSPRODUCTS_OF_ANY_PAIR_OF_EDGES_OF_A_GIVEN_TRIANGLE_ARE_EQUAL)
1871 picoVec3_t weightedNormal;
1873 float* a = xyz[*(first + 0)];
1874 float* b = xyz[*(first + 1)];
1875 float* c = xyz[*(first + 2)];
1877 _pico_subtract_vec( b, a, ba );
1878 _pico_subtract_vec( c, a, ca );
1879 _pico_cross_vec( ca, ba, weightedNormal );
1886 float* normal = normals[*(first + j)];
1887 #if (!THE_CROSSPRODUCTS_OF_ANY_PAIR_OF_EDGES_OF_A_GIVEN_TRIANGLE_ARE_EQUAL)
1888 picoVec3_t weightedNormal;
1890 float* a = xyz[*(first + ((j + 0) % 3))];
1891 float* b = xyz[*(first + ((j + 1) % 3))];
1892 float* c = xyz[*(first + ((j + 2) % 3))];
1894 _pico_subtract_vec( b, a, ba );
1895 _pico_subtract_vec( c, a, ca );
1896 _pico_cross_vec( ca, ba, weightedNormal );
1899 _pico_add_vec(weightedNormal, normal, normal);
1905 void _pico_normals_zero(picoNormalIter_t first, picoNormalIter_t last)
1907 for(; first != last; ++first)
1909 _pico_zero_vec(*first);
1913 void _pico_normals_normalize(picoNormalIter_t first, picoNormalIter_t last)
1915 for(; first != last; ++first)
1917 _pico_normalize_vec(*first);
1921 double _pico_length_vec( picoVec3_t vec )
1923 return sqrt( vec[ 0 ] * vec[ 0 ] + vec[ 1 ] * vec[ 1 ] + vec[ 2 ] * vec[ 2 ] );
1926 #define NORMAL_UNIT_LENGTH_EPSILON 0.01
1927 #define FLOAT_EQUAL_EPSILON(f, other, epsilon) (fabs(f - other) < epsilon)
1929 int _pico_normal_is_unit_length(picoVec3_t normal)
1931 return FLOAT_EQUAL_EPSILON(_pico_length_vec(normal), 1.0, NORMAL_UNIT_LENGTH_EPSILON);
1934 int _pico_normal_within_tolerance(picoVec3_t normal, picoVec3_t other)
1936 return _pico_dot_vec(normal, other) > 0.0f;
1940 void _pico_normals_assign_generated_normals(picoNormalIter_t first, picoNormalIter_t last, picoNormalIter_t generated)
1942 for(; first != last; ++first, ++generated)
1944 if(!_pico_normal_is_unit_length(*first) || !_pico_normal_within_tolerance(*first, *generated))
1946 _pico_copy_vec(*generated, *first);
1951 void PicoFixSurfaceNormals(picoSurface_t* surface)
1953 picoVec3_t* normals = (picoVec3_t*)_pico_calloc(surface->numVertexes, sizeof(picoVec3_t));
1955 _pico_normals_zero(normals, normals + surface->numVertexes);
1957 _pico_triangles_generate_weighted_normals(surface->index, surface->index + surface->numIndexes, surface->xyz, normals);
1958 _pico_vertices_combine_shared_normals(surface->xyz, surface->smoothingGroup, normals, surface->numVertexes);
1960 _pico_normals_normalize(normals, normals + surface->numVertexes);
1962 _pico_normals_assign_generated_normals(surface->normal, surface->normal + surface->numVertexes, normals);
1964 _pico_free(normals);
1969 PicoRemapModel() - sea
1970 remaps model material/etc. information using the remappings
1971 contained in the given 'remapFile' (full path to the ascii file to open)
1972 returns 1 on success or 0 on error
1975 #define _prm_error_return \
1977 _pico_free_parser( p ); \
1978 _pico_free_file( remapBuffer ); \
1982 int PicoRemapModel( picoModel_t *model, char *remapFile )
1985 picoByte_t *remapBuffer;
1990 if( model == NULL || remapFile == NULL )
1993 /* load remap file contents */
1994 _pico_load_file( remapFile,&remapBuffer,&remapBufSize );
1997 if( remapBufSize == 0 )
1998 return 1; /* file is empty: no error */
1999 if( remapBufSize < 0 )
2000 return 0; /* load failed: error */
2002 /* create a new pico parser */
2003 p = _pico_new_parser( remapBuffer, remapBufSize );
2006 /* ram is really cheap nowadays... */
2013 /* get next token in remap file */
2014 if (!_pico_parse( p,1 ))
2017 /* skip over c++ style comment lines */
2018 if (!_pico_stricmp(p->token,"//"))
2020 _pico_parse_skip_rest( p );
2024 /* block for quick material shader name remapping */
2025 /* materials { "m" (=>|->|=) "s" } */
2026 if( !_pico_stricmp(p->token, "materials" ) )
2031 if (!_pico_parse_check( p,1,"{" ))
2034 /* process assignments */
2037 picoShader_t *shader;
2041 /* get material name */
2042 if (_pico_parse( p,1 ) == NULL) break;
2043 if (!strlen(p->token)) continue;
2044 materialName = _pico_clone_alloc( p->token );
2045 if (materialName == NULL)
2049 if (p->token[0] == '{') level++;
2050 if (p->token[0] == '}') level--;
2053 /* get next token (assignment token or shader name) */
2054 if (!_pico_parse( p,0 ))
2056 _pico_free( materialName );
2059 /* skip assignment token (if present) */
2060 if (!strcmp(p->token,"=>") ||
2061 !strcmp(p->token,"->") ||
2062 !strcmp(p->token,"="))
2064 /* simply grab the next token */
2065 if (!_pico_parse( p,0 ))
2067 _pico_free( materialName );
2071 /* try to find material by name */
2072 shader = PicoFindShader( model,materialName,0 );
2074 /* we've found a material matching the name */
2077 PicoSetShaderName( shader,p->token );
2079 /* free memory used by material name */
2080 _pico_free( materialName );
2083 _pico_parse_skip_rest( p );
2086 /* block for detailed single material remappings */
2087 /* materials[ "m" ] { key data... } */
2088 else if (!_pico_stricmp(p->token,"materials["))
2090 picoShader_t *shader;
2091 char *tempMaterialName;
2094 /* get material name */
2095 if (!_pico_parse( p,0 ))
2098 /* temporary copy of material name */
2099 tempMaterialName = _pico_clone_alloc( p->token );
2100 if (tempMaterialName == NULL)
2103 /* check square closing bracket */
2104 if (!_pico_parse_check( p,0,"]" ))
2107 /* try to find material by name */
2108 shader = PicoFindShader( model,tempMaterialName,0 );
2110 /* free memory used by temporary material name */
2111 _pico_free( tempMaterialName );
2113 /* we haven't found a material matching the name */
2114 /* so we simply skip the braced section now and */
2115 /* continue parsing with the next main token */
2118 _pico_parse_skip_braced( p );
2121 /* check opening bracket */
2122 if (!_pico_parse_check( p,1,"{" ))
2125 /* process material info keys */
2129 if (_pico_parse( p,1 ) == NULL) break;
2130 if (!strlen(p->token)) continue;
2133 if (p->token[0] == '{') level++;
2134 if (p->token[0] == '}') level--;
2137 /* remap shader name */
2138 if (!_pico_stricmp(p->token,"shader"))
2140 if (!_pico_parse( p,0 )) _prm_error_return;
2141 PicoSetShaderName( shader,p->token );
2143 /* remap shader map name */
2144 else if (!_pico_stricmp(p->token,"mapname"))
2146 if (!_pico_parse( p,0 )) _prm_error_return;
2147 PicoSetShaderMapName( shader,p->token );
2149 /* remap shader's ambient color */
2150 else if (!_pico_stricmp(p->token,"ambient"))
2155 /* get vector from parser */
2156 if (!_pico_parse_vec( p,v )) _prm_error_return;
2158 /* store as color */
2159 color[ 0 ] = (picoByte_t)v[ 0 ];
2160 color[ 1 ] = (picoByte_t)v[ 1 ];
2161 color[ 2 ] = (picoByte_t)v[ 2 ];
2163 /* set new ambient color */
2164 PicoSetShaderAmbientColor( shader,color );
2166 /* remap shader's diffuse color */
2167 else if (!_pico_stricmp(p->token,"diffuse"))
2172 /* get vector from parser */
2173 if (!_pico_parse_vec( p,v )) _prm_error_return;
2175 /* store as color */
2176 color[ 0 ] = (picoByte_t)v[ 0 ];
2177 color[ 1 ] = (picoByte_t)v[ 1 ];
2178 color[ 2 ] = (picoByte_t)v[ 2 ];
2180 /* set new ambient color */
2181 PicoSetShaderDiffuseColor( shader,color );
2183 /* remap shader's specular color */
2184 else if (!_pico_stricmp(p->token,"specular"))
2189 /* get vector from parser */
2190 if (!_pico_parse_vec( p,v )) _prm_error_return;
2192 /* store as color */
2193 color[ 0 ] = (picoByte_t)v[ 0 ];
2194 color[ 1 ] = (picoByte_t)v[ 1 ];
2195 color[ 2 ] = (picoByte_t)v[ 2 ];
2197 /* set new ambient color */
2198 PicoSetShaderSpecularColor( shader,color );
2201 _pico_parse_skip_rest( p );
2204 /* end 'materials[' */
2207 /* free both parser and file buffer */
2208 _pico_free_parser( p );
2209 _pico_free_file( remapBuffer );
2211 /* return with success */
2217 PicoAddTriangleToModel() - jhefty
2218 A nice way to add individual triangles to the model.
2219 Chooses an appropriate surface based on the shader, or adds a new surface if necessary
2222 void PicoAddTriangleToModel( picoModel_t *model, picoVec3_t** xyz, picoVec3_t** normals,
2223 int numSTs, picoVec2_t **st, int numColors, picoColor_t **colors,
2224 picoShader_t* shader, picoIndex_t* smoothingGroup )
2228 picoSurface_t* workSurface = NULL;
2230 /* see if a surface already has the shader */
2231 for ( i = 0 ; i < model->numSurfaces ; i++ )
2233 workSurface = model->surface[i];
2234 if ( workSurface->shader == shader )
2240 /* no surface uses this shader yet, so create a new surface */
2241 if ( !workSurface || i >=model->numSurfaces )
2243 /* create a new surface in the model for the unique shader */
2244 workSurface = PicoNewSurface(model);
2247 _pico_printf ( PICO_ERROR , "Could not allocate a new surface!\n" );
2251 /* do surface setup */
2252 PicoSetSurfaceType( workSurface, PICO_TRIANGLES );
2253 PicoSetSurfaceName( workSurface, shader->name );
2254 PicoSetSurfaceShader( workSurface, shader );
2257 /* add the triangle data to the surface */
2258 for ( i = 0 ; i < 3 ; i++ )
2260 /* get the next free spot in the index array */
2261 int newVertIndex = PicoGetSurfaceNumIndexes ( workSurface );
2263 /* get the index of the vertex that we're going to store at newVertIndex */
2264 vertDataIndex = PicoFindSurfaceVertexNum ( workSurface , *xyz[i] , *normals[i] , numSTs , st[i] , numColors , colors[i], smoothingGroup[i]);
2266 /* the vertex wasn't found, so create a new vertex in the pool from the data we have */
2267 if ( vertDataIndex == -1 )
2269 /* find the next spot for a new vertex */
2270 vertDataIndex = PicoGetSurfaceNumVertexes ( workSurface );
2272 /* assign the data to it */
2273 PicoSetSurfaceXYZ ( workSurface ,vertDataIndex , *xyz[i] );
2274 PicoSetSurfaceNormal ( workSurface , vertDataIndex , *normals[i] );
2276 /* make sure to copy over all available ST's and colors for the vertex */
2277 for ( j = 0 ; j < numColors ; j++ )
2279 PicoSetSurfaceColor( workSurface , j , vertDataIndex , colors[i][j] );
2281 for ( j = 0 ; j < numSTs ; j++ )
2283 PicoSetSurfaceST ( workSurface , j , vertDataIndex , st[i][j] );
2286 PicoSetSurfaceSmoothingGroup ( workSurface , vertDataIndex , smoothingGroup[i] );
2289 /* add this vertex to the triangle */
2290 PicoSetSurfaceIndex ( workSurface , newVertIndex , vertDataIndex );