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)( const 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, const 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( const 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, const char *fileName )
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';
289 model = PicoModuleLoadModel(module, fileName, buffer, bufSize, frameNum);
301 /* ----------------------------------------------------------------------------
303 ---------------------------------------------------------------------------- */
307 creates a new pico model
310 picoModel_t *PicoNewModel( void )
315 model = _pico_alloc( sizeof(picoModel_t) );
320 memset( model,0,sizeof(picoModel_t) );
323 _pico_zero_bounds( model->mins,model->maxs );
325 /* set initial frame count to 1 -sea */
326 model->numFrames = 1;
328 /* return ptr to new model */
336 frees a model and all associated data
339 void PicoFreeModel( picoModel_t *model )
350 _pico_free( model->name );
352 if( model->fileName )
353 _pico_free( model->fileName );
356 for( i = 0; i < model->numShaders; i++ )
357 PicoFreeShader( model->shader[ i ] );
358 free( model->shader );
361 for( i = 0; i < model->numSurfaces; i++ )
362 PicoFreeSurface( model->surface[ i ] );
363 free( model->surface );
373 adjusts a models's memory allocations to handle the requested sizes.
374 will always grow, never shrink
377 int PicoAdjustModel( picoModel_t *model, int numShaders, int numSurfaces )
384 /* sea: null surface/shader fix (1s=>0s) */
387 if( numSurfaces < 0 )
390 /* additional shaders? */
391 while( numShaders > model->maxShaders )
393 model->maxShaders += PICO_GROW_SHADERS;
394 if( !_pico_realloc( (void *) &model->shader, model->numShaders * sizeof( *model->shader ), model->maxShaders * sizeof( *model->shader ) ) )
398 /* set shader count to higher */
399 if( numShaders > model->numShaders )
400 model->numShaders = numShaders;
402 /* additional surfaces? */
403 while( numSurfaces > model->maxSurfaces )
405 model->maxSurfaces += PICO_GROW_SURFACES;
406 if( !_pico_realloc( (void *) &model->surface, model->numSurfaces * sizeof( *model->surface ), model->maxSurfaces * sizeof( *model->surface ) ) )
410 /* set shader count to higher */
411 if( numSurfaces > model->numSurfaces )
412 model->numSurfaces = numSurfaces;
420 /* ----------------------------------------------------------------------------
422 ---------------------------------------------------------------------------- */
426 creates a new pico shader and returns its index. -sea
429 picoShader_t *PicoNewShader( picoModel_t *model )
431 picoShader_t *shader;
434 /* allocate and clear */
435 shader = _pico_alloc( sizeof(picoShader_t) );
438 memset( shader, 0, sizeof(picoShader_t) );
440 /* attach it to the model */
444 if( !PicoAdjustModel( model, model->numShaders + 1, 0 ) )
446 _pico_free( shader );
451 model->shader[ model->numShaders - 1 ] = shader;
452 shader->model = model;
455 /* setup default shader colors */
456 _pico_set_color( shader->ambientColor,0,0,0,0 );
457 _pico_set_color( shader->diffuseColor,255,255,255,1 );
458 _pico_set_color( shader->specularColor,0,0,0,0 );
460 /* no need to do this, but i do it anyway */
461 shader->transparency = 0;
462 shader->shininess = 0;
464 /* return the newly created shader */
472 frees a shader and all associated data -sea
475 void PicoFreeShader( picoShader_t *shader )
483 _pico_free( shader->name );
484 if( shader->mapName )
485 _pico_free( shader->mapName );
487 /* free the shader */
488 _pico_free( shader );
495 finds a named shader in a model
498 picoShader_t *PicoFindShader( picoModel_t *model, char *name, int caseSensitive )
504 if( model == NULL || name == NULL ) /* sea: null name fix */
508 for( i = 0; i < model->numShaders; i++ )
510 /* skip null shaders or shaders with null names */
511 if( model->shader[ i ] == NULL ||
512 model->shader[ i ]->name == NULL )
515 /* compare the shader name with name we're looking for */
518 if( !strcmp( name, model->shader[ i ]->name ) )
519 return model->shader[ i ];
521 else if( !_pico_stricmp( name, model->shader[ i ]->name ) )
522 return model->shader[ i ];
525 /* named shader not found */
531 /* ----------------------------------------------------------------------------
533 ---------------------------------------------------------------------------- */
537 creates a new pico surface
540 picoSurface_t *PicoNewSurface( picoModel_t *model )
542 picoSurface_t *surface;
543 char surfaceName[64];
545 /* allocate and clear */
546 surface = _pico_alloc( sizeof( *surface ) );
547 if( surface == NULL )
549 memset( surface, 0, sizeof( *surface ) );
551 /* attach it to the model */
555 if( !PicoAdjustModel( model, 0, model->numSurfaces + 1 ) )
557 _pico_free( surface );
562 model->surface[ model->numSurfaces - 1 ] = surface;
563 surface->model = model;
565 /* set default name */
566 sprintf( surfaceName, "Unnamed_%d", model->numSurfaces );
567 PicoSetSurfaceName( surface, surfaceName );
578 frees a surface and all associated data
580 void PicoFreeSurface( picoSurface_t *surface )
586 if( surface == NULL )
590 _pico_free( surface->xyz );
591 _pico_free( surface->normal );
592 _pico_free( surface->smoothingGroup );
593 _pico_free( surface->index );
594 _pico_free( surface->faceNormal );
597 _pico_free( surface->name );
600 for( i = 0; i < surface->numSTArrays; i++ )
601 _pico_free( surface->st[ i ] );
603 for( i = 0; i < surface->numColorArrays; i++ )
604 _pico_free( surface->color[ i ] );
605 free( surface->color );
607 /* free the surface */
608 _pico_free( surface );
615 adjusts a surface's memory allocations to handle the requested sizes.
616 will always grow, never shrink
619 int PicoAdjustSurface( picoSurface_t *surface, int numVertexes, int numSTArrays, int numColorArrays, int numIndexes, int numFaceNormals )
625 if( surface == NULL )
629 if( numVertexes < 1 )
631 if( numSTArrays < 1 )
633 if( numColorArrays < 1 )
638 /* additional vertexes? */
639 while( numVertexes > surface->maxVertexes ) /* fix */
641 surface->maxVertexes += PICO_GROW_VERTEXES;
642 if( !_pico_realloc( (void *) &surface->xyz, surface->numVertexes * sizeof( *surface->xyz ), surface->maxVertexes * sizeof( *surface->xyz ) ) )
644 if( !_pico_realloc( (void *) &surface->normal, surface->numVertexes * sizeof( *surface->normal ), surface->maxVertexes * sizeof( *surface->normal ) ) )
646 if( !_pico_realloc( (void *) &surface->smoothingGroup, surface->numVertexes * sizeof( *surface->smoothingGroup ), surface->maxVertexes * sizeof( *surface->smoothingGroup ) ) )
648 for( i = 0; i < surface->numSTArrays; i++ )
649 if( !_pico_realloc( (void*) &surface->st[ i ], surface->numVertexes * sizeof( *surface->st[ i ] ), surface->maxVertexes * sizeof( *surface->st[ i ] ) ) )
651 for( i = 0; i < surface->numColorArrays; i++ )
652 if( !_pico_realloc( (void*) &surface->color[ i ], surface->numVertexes * sizeof( *surface->color[ i ] ), surface->maxVertexes * sizeof( *surface->color[ i ] ) ) )
656 /* set vertex count to higher */
657 if( numVertexes > surface->numVertexes )
658 surface->numVertexes = numVertexes;
660 /* additional st arrays? */
661 while( numSTArrays > surface->maxSTArrays ) /* fix */
663 surface->maxSTArrays += PICO_GROW_ARRAYS;
664 if( !_pico_realloc( (void*) &surface->st, surface->numSTArrays * sizeof( *surface->st ), surface->maxSTArrays * sizeof( *surface->st ) ) )
666 while( surface->numSTArrays < numSTArrays )
668 surface->st[ surface->numSTArrays ] = _pico_alloc( surface->maxVertexes * sizeof( *surface->st[ 0 ] ) );
669 memset( surface->st[ surface->numSTArrays ], 0, surface->maxVertexes * sizeof( *surface->st[ 0 ] ) );
670 surface->numSTArrays++;
674 /* additional color arrays? */
675 while( numColorArrays > surface->maxColorArrays ) /* fix */
677 surface->maxColorArrays += PICO_GROW_ARRAYS;
678 if( !_pico_realloc( (void*) &surface->color, surface->numColorArrays * sizeof( *surface->color ), surface->maxColorArrays * sizeof( *surface->color ) ) )
680 while( surface->numColorArrays < numColorArrays )
682 surface->color[ surface->numColorArrays ] = _pico_alloc( surface->maxVertexes * sizeof( *surface->color[ 0 ] ) );
683 memset( surface->color[ surface->numColorArrays ], 0, surface->maxVertexes * sizeof( *surface->color[ 0 ] ) );
684 surface->numColorArrays++;
688 /* additional indexes? */
689 while( numIndexes > surface->maxIndexes ) /* fix */
691 surface->maxIndexes += PICO_GROW_INDEXES;
692 if( !_pico_realloc( (void*) &surface->index, surface->numIndexes * sizeof( *surface->index ), surface->maxIndexes * sizeof( *surface->index ) ) )
696 /* set index count to higher */
697 if( numIndexes > surface->numIndexes )
698 surface->numIndexes = numIndexes;
700 /* additional face normals? */
701 while( numFaceNormals > surface->maxFaceNormals ) /* fix */
703 surface->maxFaceNormals += PICO_GROW_FACES;
704 if( !_pico_realloc( (void *) &surface->faceNormal, surface->numFaceNormals * sizeof( *surface->faceNormal ), surface->maxFaceNormals * sizeof( *surface->faceNormal ) ) )
708 /* set face normal count to higher */
709 if( numFaceNormals > surface->numFaceNormals )
710 surface->numFaceNormals = numFaceNormals;
718 * Finds first matching named surface in a model.
720 picoSurface_t *PicoFindSurface(
721 picoModel_t *model, char *name, int caseSensitive )
726 if( model == NULL || name == NULL )
730 for( i = 0; i < model->numSurfaces; i++ )
732 /* skip null surfaces or surfaces with null names */
733 if( model->surface[ i ] == NULL ||
734 model->surface[ i ]->name == NULL )
737 /* compare the surface name with name we're looking for */
739 if( !strcmp(name,model->surface[ i ]->name) )
740 return model->surface[ i ];
742 if( !_pico_stricmp(name,model->surface[ i ]->name) )
743 return model->surface[ i ];
746 /* named surface not found */
752 /*----------------------------------------------------------------------------
753 PicoSet*() Setter Functions
754 ----------------------------------------------------------------------------*/
756 void PicoSetModelName( picoModel_t *model, const char *name )
758 if( model == NULL || name == NULL )
760 if( model->name != NULL )
761 _pico_free( model->name );
763 model->name = _pico_clone_alloc( name );
768 void PicoSetModelFileName( picoModel_t *model, const char *fileName )
770 if( model == NULL || fileName == NULL )
772 if( model->fileName != NULL )
773 _pico_free( model->fileName );
775 model->fileName = _pico_clone_alloc( fileName );
780 void PicoSetModelFrameNum( picoModel_t *model, int frameNum )
784 model->frameNum = frameNum;
789 void PicoSetModelNumFrames( picoModel_t *model, int numFrames )
793 model->numFrames = numFrames;
798 void PicoSetModelData( picoModel_t *model, void *data )
807 void PicoSetShaderName( picoShader_t *shader, char *name )
809 if( shader == NULL || name == NULL )
811 if( shader->name != NULL )
812 _pico_free( shader->name );
814 shader->name = _pico_clone_alloc( name );
819 void PicoSetShaderMapName( picoShader_t *shader, char *mapName )
821 if( shader == NULL || mapName == NULL )
823 if( shader->mapName != NULL )
824 _pico_free( shader->mapName );
826 shader->mapName = _pico_clone_alloc( mapName );
831 void PicoSetShaderAmbientColor( picoShader_t *shader, picoColor_t color )
833 if( shader == NULL || color == NULL )
835 shader->ambientColor[ 0 ] = color[ 0 ];
836 shader->ambientColor[ 1 ] = color[ 1 ];
837 shader->ambientColor[ 2 ] = color[ 2 ];
838 shader->ambientColor[ 3 ] = color[ 3 ];
843 void PicoSetShaderDiffuseColor( picoShader_t *shader, picoColor_t color )
845 if( shader == NULL || color == NULL )
847 shader->diffuseColor[ 0 ] = color[ 0 ];
848 shader->diffuseColor[ 1 ] = color[ 1 ];
849 shader->diffuseColor[ 2 ] = color[ 2 ];
850 shader->diffuseColor[ 3 ] = color[ 3 ];
855 void PicoSetShaderSpecularColor( picoShader_t *shader, picoColor_t color )
857 if( shader == NULL || color == NULL )
859 shader->specularColor[ 0 ] = color[ 0 ];
860 shader->specularColor[ 1 ] = color[ 1 ];
861 shader->specularColor[ 2 ] = color[ 2 ];
862 shader->specularColor[ 3 ] = color[ 3 ];
867 void PicoSetShaderTransparency( picoShader_t *shader, float value )
871 shader->transparency = value;
873 /* cap to 0..1 range */
874 if (shader->transparency < 0.0)
875 shader->transparency = 0.0;
876 if (shader->transparency > 1.0)
877 shader->transparency = 1.0;
882 void PicoSetShaderShininess( picoShader_t *shader, float value )
886 shader->shininess = value;
888 /* cap to 0..127 range */
889 if (shader->shininess < 0.0)
890 shader->shininess = 0.0;
891 if (shader->shininess > 127.0)
892 shader->shininess = 127.0;
897 void PicoSetSurfaceData( picoSurface_t *surface, void *data )
899 if( surface == NULL )
901 surface->data = data;
906 void PicoSetSurfaceType( picoSurface_t *surface, picoSurfaceType_t type )
908 if( surface == NULL )
910 surface->type = type;
915 void PicoSetSurfaceName( picoSurface_t *surface, const char *name )
917 if( surface == NULL || name == NULL )
919 if( surface->name != NULL )
920 _pico_free( surface->name );
922 surface->name = _pico_clone_alloc( name );
927 void PicoSetSurfaceShader( picoSurface_t *surface, picoShader_t *shader )
929 if( surface == NULL )
931 surface->shader = shader;
936 void PicoSetSurfaceXYZ( picoSurface_t *surface, int num, picoVec3_t xyz )
938 if( surface == NULL || num < 0 || xyz == NULL )
940 if( !PicoAdjustSurface( surface, num + 1, 0, 0, 0, 0 ) )
942 _pico_copy_vec( xyz, surface->xyz[ num ] );
943 if( surface->model != NULL )
944 _pico_expand_bounds( xyz, surface->model->mins, surface->model->maxs );
949 void PicoSetSurfaceNormal( picoSurface_t *surface, int num, picoVec3_t normal )
951 if( surface == NULL || num < 0 || normal == NULL )
953 if( !PicoAdjustSurface( surface, num + 1, 0, 0, 0, 0 ) )
955 _pico_copy_vec( normal, surface->normal[ num ] );
960 void PicoSetSurfaceST( picoSurface_t *surface, int array, int num, picoVec2_t st )
962 if( surface == NULL || num < 0 || st == NULL )
964 if( !PicoAdjustSurface( surface, num + 1, array + 1, 0, 0, 0 ) )
966 surface->st[ array ][ num ][ 0 ] = st[ 0 ];
967 surface->st[ array ][ num ][ 1 ] = st[ 1 ];
972 void PicoSetSurfaceColor( picoSurface_t *surface, int array, int num, picoColor_t color )
974 if( surface == NULL || num < 0 || color == NULL )
976 if( !PicoAdjustSurface( surface, num + 1, 0, array + 1, 0, 0 ) )
978 surface->color[ array ][ num ][ 0 ] = color[ 0 ];
979 surface->color[ array ][ num ][ 1 ] = color[ 1 ];
980 surface->color[ array ][ num ][ 2 ] = color[ 2 ];
981 surface->color[ array ][ num ][ 3 ] = color[ 3 ];
986 void PicoSetSurfaceIndex( picoSurface_t *surface, int num, picoIndex_t index )
988 if( surface == NULL || num < 0 )
990 if( !PicoAdjustSurface( surface, 0, 0, 0, num + 1, 0 ) )
992 surface->index[ num ] = index;
997 void PicoSetSurfaceIndexes( picoSurface_t *surface, int num, picoIndex_t *index, int count )
999 if( num < 0 || index == NULL || count < 1 )
1001 if( !PicoAdjustSurface( surface, 0, 0, 0, num + count, 0 ) )
1003 memcpy( &surface->index[ num ], index, count * sizeof( surface->index[ num ] ) );
1008 void PicoSetFaceNormal( picoSurface_t *surface, int num, picoVec3_t normal )
1010 if( surface == NULL || num < 0 || normal == NULL )
1012 if( !PicoAdjustSurface( surface, 0, 0, 0, 0, num + 1 ) )
1014 _pico_copy_vec( normal, surface->faceNormal[ num ] );
1018 void PicoSetSurfaceSmoothingGroup( picoSurface_t *surface, int num, picoIndex_t smoothingGroup )
1022 if( !PicoAdjustSurface( surface, num + 1, 0, 0, 0, 0 ) )
1024 surface->smoothingGroup[ num ] = smoothingGroup;
1028 void PicoSetSurfaceSpecial( picoSurface_t *surface, int num, int special )
1030 if( surface == NULL || num < 0 || num >= PICO_MAX_SPECIAL )
1032 surface->special[ num ] = special;
1037 /*----------------------------------------------------------------------------
1038 PicoGet*() Getter Functions
1039 ----------------------------------------------------------------------------*/
1041 char *PicoGetModelName( picoModel_t *model )
1045 if( model->name == NULL)
1052 char *PicoGetModelFileName( picoModel_t *model )
1056 if( model->fileName == NULL)
1058 return model->fileName;
1063 int PicoGetModelFrameNum( picoModel_t *model )
1067 return model->frameNum;
1072 int PicoGetModelNumFrames( picoModel_t *model )
1076 return model->numFrames;
1081 void *PicoGetModelData( picoModel_t *model )
1090 int PicoGetModelNumShaders( picoModel_t *model )
1094 return model->numShaders;
1099 picoShader_t *PicoGetModelShader( picoModel_t *model, int num )
1101 /* a few sanity checks */
1104 if( model->shader == NULL)
1106 if( num < 0 || num >= model->numShaders )
1109 /* return the shader */
1110 return model->shader[ num ];
1115 int PicoGetModelNumSurfaces( picoModel_t *model )
1119 return model->numSurfaces;
1124 picoSurface_t *PicoGetModelSurface( picoModel_t *model, int num )
1126 /* a few sanity checks */
1129 if( model->surface == NULL)
1131 if( num < 0 || num >= model->numSurfaces )
1134 /* return the surface */
1135 return model->surface[ num ];
1140 int PicoGetModelTotalVertexes( picoModel_t *model )
1147 if( model->surface == NULL )
1151 for( i = 0; i < model->numSurfaces; i++ )
1152 count += PicoGetSurfaceNumVertexes( model->surface[ i ] );
1159 int PicoGetModelTotalIndexes( picoModel_t *model )
1166 if( model->surface == NULL )
1170 for( i = 0; i < model->numSurfaces; i++ )
1171 count += PicoGetSurfaceNumIndexes( model->surface[ i ] );
1178 char *PicoGetShaderName( picoShader_t *shader )
1180 if( shader == NULL )
1182 if( shader->name == NULL)
1184 return shader->name;
1189 char *PicoGetShaderMapName( picoShader_t *shader )
1191 if( shader == NULL )
1193 if( shader->mapName == NULL)
1195 return shader->mapName;
1200 picoByte_t *PicoGetShaderAmbientColor( picoShader_t *shader )
1202 if( shader == NULL )
1204 return shader->ambientColor;
1209 picoByte_t *PicoGetShaderDiffuseColor( picoShader_t *shader )
1211 if( shader == NULL )
1213 return shader->diffuseColor;
1218 picoByte_t *PicoGetShaderSpecularColor( picoShader_t *shader )
1220 if( shader == NULL )
1222 return shader->specularColor;
1227 float PicoGetShaderTransparency( picoShader_t *shader )
1229 if( shader == NULL )
1231 return shader->transparency;
1236 float PicoGetShaderShininess( picoShader_t *shader )
1238 if( shader == NULL )
1240 return shader->shininess;
1245 void *PicoGetSurfaceData( picoSurface_t *surface )
1247 if( surface == NULL )
1249 return surface->data;
1254 picoSurfaceType_t PicoGetSurfaceType( picoSurface_t *surface )
1256 if( surface == NULL )
1258 return surface->type;
1263 char *PicoGetSurfaceName( picoSurface_t *surface )
1265 if( surface == NULL )
1267 if( surface->name == NULL )
1269 return surface->name;
1274 picoShader_t *PicoGetSurfaceShader( picoSurface_t *surface )
1276 if( surface == NULL )
1278 return surface->shader;
1283 int PicoGetSurfaceNumVertexes( picoSurface_t *surface )
1285 if( surface == NULL )
1287 return surface->numVertexes;
1292 picoVec_t *PicoGetSurfaceXYZ( picoSurface_t *surface, int num )
1294 if( surface == NULL || num < 0 || num > surface->numVertexes )
1296 return surface->xyz[ num ];
1301 picoVec_t *PicoGetSurfaceNormal( picoSurface_t *surface, int num )
1303 if( surface == NULL || num < 0 || num > surface->numVertexes )
1305 return surface->normal[ num ];
1310 picoVec_t *PicoGetSurfaceST( picoSurface_t *surface, int array, int num )
1312 if( surface == NULL || array < 0 || array > surface->numSTArrays || num < 0 || num > surface->numVertexes )
1314 return surface->st[ array ][ num ];
1319 picoByte_t *PicoGetSurfaceColor( picoSurface_t *surface, int array, int num )
1321 if( surface == NULL || array < 0 || array > surface->numColorArrays || num < 0 || num > surface->numVertexes )
1323 return surface->color[ array ][ num ];
1328 int PicoGetSurfaceNumIndexes( picoSurface_t *surface )
1330 if( surface == NULL )
1332 return surface->numIndexes;
1337 picoIndex_t PicoGetSurfaceIndex( picoSurface_t *surface, int num )
1339 if( surface == NULL || num < 0 || num > surface->numIndexes )
1341 return surface->index[ num ];
1346 picoIndex_t *PicoGetSurfaceIndexes( picoSurface_t *surface, int num )
1348 if( surface == NULL || num < 0 || num > surface->numIndexes )
1350 return &surface->index[ num ];
1354 picoVec_t *PicoGetFaceNormal( picoSurface_t *surface, int num )
1356 if( surface == NULL || num < 0 || num > surface->numFaceNormals )
1358 return surface->faceNormal[ num ];
1361 picoIndex_t PicoGetSurfaceSmoothingGroup( picoSurface_t *surface, int num )
1363 if( surface == NULL || num < 0 || num > surface->numVertexes )
1365 return surface->smoothingGroup[ num ];
1369 int PicoGetSurfaceSpecial( picoSurface_t *surface, int num )
1371 if( surface == NULL || num < 0 || num >= PICO_MAX_SPECIAL )
1373 return surface->special[ num ];
1378 /* ----------------------------------------------------------------------------
1379 hashtable related functions
1380 ---------------------------------------------------------------------------- */
1382 /* hashtable code for faster vertex lookups */
1383 //#define HASHTABLE_SIZE 32768 // 2048 /* power of 2, use & */
1384 #define HASHTABLE_SIZE 7919 // 32749 // 2039 /* prime, use % */
1386 int PicoGetHashTableSize( void )
1388 return HASHTABLE_SIZE;
1391 #define HASH_USE_EPSILON
1393 #ifdef HASH_USE_EPSILON
1394 #define HASH_XYZ_EPSILON 0.01f
1395 #define HASH_XYZ_EPSILONSPACE_MULTIPLIER 1.f / HASH_XYZ_EPSILON
1396 #define HASH_ST_EPSILON 0.0001f
1397 #define HASH_NORMAL_EPSILON 0.02f
1400 unsigned int PicoVertexCoordGenerateHash( picoVec3_t xyz )
1402 unsigned int hash = 0;
1404 #ifndef HASH_USE_EPSILON
1405 hash += ~(*((unsigned int*) &xyz[ 0 ]) << 15);
1406 hash ^= (*((unsigned int*) &xyz[ 0 ]) >> 10);
1407 hash += (*((unsigned int*) &xyz[ 1 ]) << 3);
1408 hash ^= (*((unsigned int*) &xyz[ 1 ]) >> 6);
1409 hash += ~(*((unsigned int*) &xyz[ 2 ]) << 11);
1410 hash ^= (*((unsigned int*) &xyz[ 2 ]) >> 16);
1412 picoVec3_t xyz_epsilonspace;
1414 _pico_scale_vec( xyz, HASH_XYZ_EPSILONSPACE_MULTIPLIER, xyz_epsilonspace );
1415 xyz_epsilonspace[ 0 ] = (float)floor(xyz_epsilonspace[ 0 ]);
1416 xyz_epsilonspace[ 1 ] = (float)floor(xyz_epsilonspace[ 1 ]);
1417 xyz_epsilonspace[ 2 ] = (float)floor(xyz_epsilonspace[ 2 ]);
1419 hash += ~(*((unsigned int*) &xyz_epsilonspace[ 0 ]) << 15);
1420 hash ^= (*((unsigned int*) &xyz_epsilonspace[ 0 ]) >> 10);
1421 hash += (*((unsigned int*) &xyz_epsilonspace[ 1 ]) << 3);
1422 hash ^= (*((unsigned int*) &xyz_epsilonspace[ 1 ]) >> 6);
1423 hash += ~(*((unsigned int*) &xyz_epsilonspace[ 2 ]) << 11);
1424 hash ^= (*((unsigned int*) &xyz_epsilonspace[ 2 ]) >> 16);
1427 //hash = hash & (HASHTABLE_SIZE-1);
1428 hash = hash % (HASHTABLE_SIZE);
1432 picoVertexCombinationHash_t **PicoNewVertexCombinationHashTable( void )
1434 picoVertexCombinationHash_t **hashTable = _pico_alloc( HASHTABLE_SIZE * sizeof(picoVertexCombinationHash_t*) );
1436 memset( hashTable, 0, HASHTABLE_SIZE * sizeof(picoVertexCombinationHash_t*) );
1441 void PicoFreeVertexCombinationHashTable( picoVertexCombinationHash_t **hashTable )
1444 picoVertexCombinationHash_t *vertexCombinationHash;
1445 picoVertexCombinationHash_t *nextVertexCombinationHash;
1448 if (hashTable == NULL)
1451 for( i = 0; i < HASHTABLE_SIZE; i++ )
1455 nextVertexCombinationHash = NULL;
1457 for( vertexCombinationHash = hashTable[ i ]; vertexCombinationHash; vertexCombinationHash = nextVertexCombinationHash )
1459 nextVertexCombinationHash = vertexCombinationHash->next;
1460 if (vertexCombinationHash->data != NULL)
1462 _pico_free( vertexCombinationHash->data );
1464 _pico_free( vertexCombinationHash );
1469 _pico_free( hashTable );
1472 picoVertexCombinationHash_t *PicoFindVertexCombinationInHashTable( picoVertexCombinationHash_t **hashTable, picoVec3_t xyz, picoVec3_t normal, picoVec3_t st, picoColor_t color )
1475 picoVertexCombinationHash_t *vertexCombinationHash;
1478 if (hashTable == NULL || xyz == NULL || normal == NULL || st == NULL || color == NULL )
1481 hash = PicoVertexCoordGenerateHash( xyz );
1483 for( vertexCombinationHash = hashTable[ hash ]; vertexCombinationHash; vertexCombinationHash = vertexCombinationHash->next )
1485 #ifndef HASH_USE_EPSILON
1487 if( (vertexCombinationHash->vcd.xyz[ 0 ] != xyz[ 0 ] || vertexCombinationHash->vcd.xyz[ 1 ] != xyz[ 1 ] || vertexCombinationHash->vcd.xyz[ 2 ] != xyz[ 2 ]) )
1491 if( (vertexCombinationHash->vcd.normal[ 0 ] != normal[ 0 ] || vertexCombinationHash->vcd.normal[ 1 ] != normal[ 1 ] || vertexCombinationHash->vcd.normal[ 2 ] != normal[ 2 ]) )
1495 if( vertexCombinationHash->vcd.st[ 0 ] != st[ 0 ] || vertexCombinationHash->vcd.st[ 1 ] != st[ 1 ] )
1499 if( ( fabs(xyz[ 0 ] - vertexCombinationHash->vcd.xyz[ 0 ]) ) > HASH_XYZ_EPSILON ||
1500 ( fabs(xyz[ 1 ] - vertexCombinationHash->vcd.xyz[ 1 ]) ) > HASH_XYZ_EPSILON ||
1501 ( fabs(xyz[ 2 ] - vertexCombinationHash->vcd.xyz[ 2 ]) ) > HASH_XYZ_EPSILON )
1505 if( ( fabs(normal[ 0 ] - vertexCombinationHash->vcd.normal[ 0 ]) ) > HASH_NORMAL_EPSILON ||
1506 ( fabs(normal[ 1 ] - vertexCombinationHash->vcd.normal[ 1 ]) ) > HASH_NORMAL_EPSILON ||
1507 ( fabs(normal[ 2 ] - vertexCombinationHash->vcd.normal[ 2 ]) ) > HASH_NORMAL_EPSILON )
1511 if( ( fabs(st[ 0 ] - vertexCombinationHash->vcd.st[ 0 ]) ) > HASH_ST_EPSILON ||
1512 ( fabs(st[ 1 ] - vertexCombinationHash->vcd.st[ 1 ]) ) > HASH_ST_EPSILON )
1517 if( *((int*) vertexCombinationHash->vcd.color) != *((int*) color) )
1521 return vertexCombinationHash;
1527 picoVertexCombinationHash_t *PicoAddVertexCombinationToHashTable( picoVertexCombinationHash_t **hashTable, picoVec3_t xyz, picoVec3_t normal, picoVec3_t st, picoColor_t color, picoIndex_t index )
1530 picoVertexCombinationHash_t *vertexCombinationHash;
1533 if (hashTable == NULL || xyz == NULL || normal == NULL || st == NULL || color == NULL )
1536 vertexCombinationHash = _pico_alloc( sizeof(picoVertexCombinationHash_t) );
1538 if (!vertexCombinationHash)
1541 hash = PicoVertexCoordGenerateHash( xyz );
1543 _pico_copy_vec( xyz, vertexCombinationHash->vcd.xyz );
1544 _pico_copy_vec( normal, vertexCombinationHash->vcd.normal );
1545 _pico_copy_vec2( st, vertexCombinationHash->vcd.st );
1546 _pico_copy_color( color, vertexCombinationHash->vcd.color );
1547 vertexCombinationHash->index = index;
1548 vertexCombinationHash->data = NULL;
1549 vertexCombinationHash->next = hashTable[ hash ];
1550 hashTable[ hash ] = vertexCombinationHash;
1552 return vertexCombinationHash;
1555 /* ----------------------------------------------------------------------------
1556 specialized routines
1557 ---------------------------------------------------------------------------- */
1560 PicoFindSurfaceVertex()
1561 finds a vertex matching the set parameters
1562 fixme: needs non-naive algorithm
1565 int PicoFindSurfaceVertexNum( picoSurface_t *surface, picoVec3_t xyz, picoVec3_t normal, int numSTs, picoVec2_t *st, int numColors, picoColor_t *color, picoIndex_t smoothingGroup)
1571 if( surface == NULL || surface->numVertexes <= 0 )
1574 /* walk vertex list */
1575 for( i = 0; i < surface->numVertexes; i++ )
1578 if( xyz != NULL && (surface->xyz[ i ][ 0 ] != xyz[ 0 ] || surface->xyz[ i ][ 1 ] != xyz[ 1 ] || surface->xyz[ i ][ 2 ] != xyz[ 2 ]) )
1582 if( normal != NULL && (surface->normal[ i ][ 0 ] != normal[ 0 ] || surface->normal[ i ][ 1 ] != normal[ 1 ] || surface->normal[ i ][ 2 ] != normal[ 2 ]) )
1586 if( surface->smoothingGroup[ i ] != smoothingGroup )
1590 if( numSTs > 0 && st != NULL )
1592 for( j = 0; j < numSTs; j++ )
1594 if( surface->st[ j ][ i ][ 0 ] != st[ j ][ 0 ] || surface->st[ j ][ i ][ 1 ] != st[ j ][ 1 ] )
1602 if( numColors > 0 && color != NULL )
1604 for( j = 0; j < numSTs; j++ )
1606 if( *((int*) surface->color[ j ]) != *((int*) color[ j ]) )
1609 if( j != numColors )
1613 /* vertex matches */
1624 typedef struct _IndexArray IndexArray;
1631 void indexarray_push_back(IndexArray* self, picoIndex_t value)
1633 *self->last++ = value;
1636 size_t indexarray_size(IndexArray* self)
1638 return self->last - self->data;
1641 void indexarray_reserve(IndexArray* self, size_t size)
1643 self->data = self->last = _pico_calloc(size, sizeof(picoIndex_t));
1646 void indexarray_clear(IndexArray* self)
1648 _pico_free(self->data);
1651 typedef struct _BinaryTreeNode BinaryTreeNode;
1652 struct _BinaryTreeNode
1658 typedef struct _BinaryTree BinaryTree;
1661 BinaryTreeNode* data;
1662 BinaryTreeNode* last;
1665 void binarytree_extend(BinaryTree* self)
1667 self->last->left = 0;
1668 self->last->right = 0;
1672 size_t binarytree_size(BinaryTree* self)
1674 return self->last - self->data;
1677 void binarytree_reserve(BinaryTree* self, size_t size)
1679 self->data = self->last = _pico_calloc(size, sizeof(BinaryTreeNode));
1682 void binarytree_clear(BinaryTree* self)
1684 _pico_free(self->data);
1687 typedef int (*LessFunc)(void*, picoIndex_t, picoIndex_t);
1689 typedef struct _UniqueIndices UniqueIndices;
1690 struct _UniqueIndices
1698 size_t UniqueIndices_size(UniqueIndices* self)
1700 return binarytree_size(&self->tree);
1703 void UniqueIndices_reserve(UniqueIndices* self, size_t size)
1705 binarytree_reserve(&self->tree, size);
1706 indexarray_reserve(&self->indices, size);
1709 void UniqueIndices_init(UniqueIndices* self, LessFunc lessFunc, void* lessData)
1711 self->lessFunc = lessFunc;
1712 self->lessData = lessData;
1715 void UniqueIndices_destroy(UniqueIndices* self)
1717 binarytree_clear(&self->tree);
1718 indexarray_clear(&self->indices);
1722 picoIndex_t UniqueIndices_find_or_insert(UniqueIndices* self, picoIndex_t value)
1724 picoIndex_t index = 0;
1728 if(self->lessFunc(self->lessData, value, self->indices.data[index]))
1730 BinaryTreeNode* node = self->tree.data + index;
1738 node->left = (picoIndex_t)binarytree_size(&self->tree);
1739 binarytree_extend(&self->tree);
1740 indexarray_push_back(&self->indices, value);
1744 if(self->lessFunc(self->lessData, self->indices.data[index], value))
1746 BinaryTreeNode* node = self->tree.data + index;
1747 if(node->right != 0)
1749 index = node->right;
1754 node->right = (picoIndex_t)binarytree_size(&self->tree);
1755 binarytree_extend(&self->tree);
1756 indexarray_push_back(&self->indices, value);
1765 picoIndex_t UniqueIndices_insert(UniqueIndices* self, picoIndex_t value)
1767 if(self->tree.data == self->tree.last)
1769 binarytree_extend(&self->tree);
1770 indexarray_push_back(&self->indices, value);
1775 return UniqueIndices_find_or_insert(self, value);
1779 typedef struct picoSmoothVertices_s picoSmoothVertices_t;
1780 struct picoSmoothVertices_s
1783 picoIndex_t* smoothingGroups;
1786 int lessSmoothVertex(void* data, picoIndex_t first, picoIndex_t second)
1788 picoSmoothVertices_t* smoothVertices = data;
1790 if(smoothVertices->xyz[first][0] != smoothVertices->xyz[second][0])
1792 return smoothVertices->xyz[first][0] < smoothVertices->xyz[second][0];
1794 if(smoothVertices->xyz[first][1] != smoothVertices->xyz[second][1])
1796 return smoothVertices->xyz[first][1] < smoothVertices->xyz[second][1];
1798 if(smoothVertices->xyz[first][2] != smoothVertices->xyz[second][2])
1800 return smoothVertices->xyz[first][2] < smoothVertices->xyz[second][2];
1802 if(smoothVertices->smoothingGroups[first] != smoothVertices->smoothingGroups[second])
1804 return smoothVertices->smoothingGroups[first] < smoothVertices->smoothingGroups[second];
1809 void _pico_vertices_combine_shared_normals(picoVec3_t* xyz, picoIndex_t* smoothingGroups, picoVec3_t* normals, picoIndex_t numVertices)
1811 UniqueIndices vertices;
1813 picoSmoothVertices_t smoothVertices = { xyz, smoothingGroups };
1814 UniqueIndices_init(&vertices, lessSmoothVertex, &smoothVertices);
1815 UniqueIndices_reserve(&vertices, numVertices);
1816 indexarray_reserve(&indices, numVertices);
1821 for(; i < numVertices; ++i)
1823 size_t size = UniqueIndices_size(&vertices);
1824 picoIndex_t index = UniqueIndices_insert(&vertices, i);
1825 if((size_t)index != size)
1827 float* normal = normals[vertices.indices.data[index]];
1828 _pico_add_vec(normal, normals[i], normal);
1830 indexarray_push_back(&indices, index);
1835 picoIndex_t maxIndex = 0;
1836 picoIndex_t* i = indices.data;
1837 for(; i != indices.last; ++i)
1841 _pico_copy_vec(normals[vertices.indices.data[*i]], normals[i - indices.data]);
1850 UniqueIndices_destroy(&vertices);
1851 indexarray_clear(&indices);
1854 typedef picoVec3_t* picoNormalIter_t;
1855 typedef picoIndex_t* picoIndexIter_t;
1857 #define THE_CROSSPRODUCTS_OF_ANY_PAIR_OF_EDGES_OF_A_GIVEN_TRIANGLE_ARE_EQUAL 1
1859 void _pico_triangles_generate_weighted_normals(picoIndexIter_t first, picoIndexIter_t end, picoVec3_t* xyz, picoVec3_t* normals)
1861 for(; first != end; first += 3)
1863 #if (THE_CROSSPRODUCTS_OF_ANY_PAIR_OF_EDGES_OF_A_GIVEN_TRIANGLE_ARE_EQUAL)
1864 picoVec3_t weightedNormal;
1866 float* a = xyz[*(first + 0)];
1867 float* b = xyz[*(first + 1)];
1868 float* c = xyz[*(first + 2)];
1870 _pico_subtract_vec( b, a, ba );
1871 _pico_subtract_vec( c, a, ca );
1872 _pico_cross_vec( ca, ba, weightedNormal );
1879 float* normal = normals[*(first + j)];
1880 #if (!THE_CROSSPRODUCTS_OF_ANY_PAIR_OF_EDGES_OF_A_GIVEN_TRIANGLE_ARE_EQUAL)
1881 picoVec3_t weightedNormal;
1883 float* a = xyz[*(first + ((j + 0) % 3))];
1884 float* b = xyz[*(first + ((j + 1) % 3))];
1885 float* c = xyz[*(first + ((j + 2) % 3))];
1887 _pico_subtract_vec( b, a, ba );
1888 _pico_subtract_vec( c, a, ca );
1889 _pico_cross_vec( ca, ba, weightedNormal );
1892 _pico_add_vec(weightedNormal, normal, normal);
1898 void _pico_normals_zero(picoNormalIter_t first, picoNormalIter_t last)
1900 for(; first != last; ++first)
1902 _pico_zero_vec(*first);
1906 void _pico_normals_normalize(picoNormalIter_t first, picoNormalIter_t last)
1908 for(; first != last; ++first)
1910 _pico_normalize_vec(*first);
1914 double _pico_length_vec( picoVec3_t vec )
1916 return sqrt( vec[ 0 ] * vec[ 0 ] + vec[ 1 ] * vec[ 1 ] + vec[ 2 ] * vec[ 2 ] );
1919 #define NORMAL_UNIT_LENGTH_EPSILON 0.01
1920 #define FLOAT_EQUAL_EPSILON(f, other, epsilon) (fabs(f - other) < epsilon)
1922 int _pico_normal_is_unit_length(picoVec3_t normal)
1924 return FLOAT_EQUAL_EPSILON(_pico_length_vec(normal), 1.0, NORMAL_UNIT_LENGTH_EPSILON);
1927 int _pico_normal_within_tolerance(picoVec3_t normal, picoVec3_t other)
1929 return _pico_dot_vec(normal, other) > 0.0f;
1933 void _pico_normals_assign_generated_normals(picoNormalIter_t first, picoNormalIter_t last, picoNormalIter_t generated)
1935 for(; first != last; ++first, ++generated)
1937 if(!_pico_normal_is_unit_length(*first) || !_pico_normal_within_tolerance(*first, *generated))
1939 _pico_copy_vec(*generated, *first);
1944 void PicoFixSurfaceNormals(picoSurface_t* surface)
1946 picoVec3_t* normals = (picoVec3_t*)_pico_calloc(surface->numVertexes, sizeof(picoVec3_t));
1948 _pico_normals_zero(normals, normals + surface->numVertexes);
1950 _pico_triangles_generate_weighted_normals(surface->index, surface->index + surface->numIndexes, surface->xyz, normals);
1951 _pico_vertices_combine_shared_normals(surface->xyz, surface->smoothingGroup, normals, surface->numVertexes);
1953 _pico_normals_normalize(normals, normals + surface->numVertexes);
1955 _pico_normals_assign_generated_normals(surface->normal, surface->normal + surface->numVertexes, normals);
1957 _pico_free(normals);
1962 PicoRemapModel() - sea
1963 remaps model material/etc. information using the remappings
1964 contained in the given 'remapFile' (full path to the ascii file to open)
1965 returns 1 on success or 0 on error
1968 #define _prm_error_return \
1970 _pico_free_parser( p ); \
1971 _pico_free_file( remapBuffer ); \
1975 int PicoRemapModel( picoModel_t *model, char *remapFile )
1978 picoByte_t *remapBuffer;
1983 if( model == NULL || remapFile == NULL )
1986 /* load remap file contents */
1987 _pico_load_file( remapFile,&remapBuffer,&remapBufSize );
1990 if( remapBufSize == 0 )
1991 return 1; /* file is empty: no error */
1992 if( remapBufSize < 0 )
1993 return 0; /* load failed: error */
1995 /* create a new pico parser */
1996 p = _pico_new_parser( remapBuffer, remapBufSize );
1999 /* ram is really cheap nowadays... */
2006 /* get next token in remap file */
2007 if (!_pico_parse( p,1 ))
2010 /* skip over c++ style comment lines */
2011 if (!_pico_stricmp(p->token,"//"))
2013 _pico_parse_skip_rest( p );
2017 /* block for quick material shader name remapping */
2018 /* materials { "m" (=>|->|=) "s" } */
2019 if( !_pico_stricmp(p->token, "materials" ) )
2024 if (!_pico_parse_check( p,1,"{" ))
2027 /* process assignments */
2030 picoShader_t *shader;
2034 /* get material name */
2035 if (_pico_parse( p,1 ) == NULL) break;
2036 if (!strlen(p->token)) continue;
2037 materialName = _pico_clone_alloc( p->token );
2038 if (materialName == NULL)
2042 if (p->token[0] == '{') level++;
2043 if (p->token[0] == '}') level--;
2046 /* get next token (assignment token or shader name) */
2047 if (!_pico_parse( p,0 ))
2049 _pico_free( materialName );
2052 /* skip assignment token (if present) */
2053 if (!strcmp(p->token,"=>") ||
2054 !strcmp(p->token,"->") ||
2055 !strcmp(p->token,"="))
2057 /* simply grab the next token */
2058 if (!_pico_parse( p,0 ))
2060 _pico_free( materialName );
2064 /* try to find material by name */
2065 shader = PicoFindShader( model,materialName,0 );
2067 /* we've found a material matching the name */
2070 PicoSetShaderName( shader,p->token );
2072 /* free memory used by material name */
2073 _pico_free( materialName );
2076 _pico_parse_skip_rest( p );
2079 /* block for detailed single material remappings */
2080 /* materials[ "m" ] { key data... } */
2081 else if (!_pico_stricmp(p->token,"materials["))
2083 picoShader_t *shader;
2084 char *tempMaterialName;
2087 /* get material name */
2088 if (!_pico_parse( p,0 ))
2091 /* temporary copy of material name */
2092 tempMaterialName = _pico_clone_alloc( p->token );
2093 if (tempMaterialName == NULL)
2096 /* check square closing bracket */
2097 if (!_pico_parse_check( p,0,"]" ))
2100 /* try to find material by name */
2101 shader = PicoFindShader( model,tempMaterialName,0 );
2103 /* free memory used by temporary material name */
2104 _pico_free( tempMaterialName );
2106 /* we haven't found a material matching the name */
2107 /* so we simply skip the braced section now and */
2108 /* continue parsing with the next main token */
2111 _pico_parse_skip_braced( p );
2114 /* check opening bracket */
2115 if (!_pico_parse_check( p,1,"{" ))
2118 /* process material info keys */
2122 if (_pico_parse( p,1 ) == NULL) break;
2123 if (!strlen(p->token)) continue;
2126 if (p->token[0] == '{') level++;
2127 if (p->token[0] == '}') level--;
2130 /* remap shader name */
2131 if (!_pico_stricmp(p->token,"shader"))
2133 if (!_pico_parse( p,0 )) _prm_error_return;
2134 PicoSetShaderName( shader,p->token );
2136 /* remap shader map name */
2137 else if (!_pico_stricmp(p->token,"mapname"))
2139 if (!_pico_parse( p,0 )) _prm_error_return;
2140 PicoSetShaderMapName( shader,p->token );
2142 /* remap shader's ambient color */
2143 else if (!_pico_stricmp(p->token,"ambient"))
2148 /* get vector from parser */
2149 if (!_pico_parse_vec( p,v )) _prm_error_return;
2151 /* store as color */
2152 color[ 0 ] = (picoByte_t)v[ 0 ];
2153 color[ 1 ] = (picoByte_t)v[ 1 ];
2154 color[ 2 ] = (picoByte_t)v[ 2 ];
2156 /* set new ambient color */
2157 PicoSetShaderAmbientColor( shader,color );
2159 /* remap shader's diffuse color */
2160 else if (!_pico_stricmp(p->token,"diffuse"))
2165 /* get vector from parser */
2166 if (!_pico_parse_vec( p,v )) _prm_error_return;
2168 /* store as color */
2169 color[ 0 ] = (picoByte_t)v[ 0 ];
2170 color[ 1 ] = (picoByte_t)v[ 1 ];
2171 color[ 2 ] = (picoByte_t)v[ 2 ];
2173 /* set new ambient color */
2174 PicoSetShaderDiffuseColor( shader,color );
2176 /* remap shader's specular color */
2177 else if (!_pico_stricmp(p->token,"specular"))
2182 /* get vector from parser */
2183 if (!_pico_parse_vec( p,v )) _prm_error_return;
2185 /* store as color */
2186 color[ 0 ] = (picoByte_t)v[ 0 ];
2187 color[ 1 ] = (picoByte_t)v[ 1 ];
2188 color[ 2 ] = (picoByte_t)v[ 2 ];
2190 /* set new ambient color */
2191 PicoSetShaderSpecularColor( shader,color );
2194 _pico_parse_skip_rest( p );
2197 /* end 'materials[' */
2200 /* free both parser and file buffer */
2201 _pico_free_parser( p );
2202 _pico_free_file( remapBuffer );
2204 /* return with success */
2210 PicoAddTriangleToModel() - jhefty
2211 A nice way to add individual triangles to the model.
2212 Chooses an appropriate surface based on the shader, or adds a new surface if necessary
2215 void PicoAddTriangleToModel( picoModel_t *model, picoVec3_t** xyz, picoVec3_t** normals,
2216 int numSTs, picoVec2_t **st, int numColors, picoColor_t **colors,
2217 picoShader_t* shader, const char *name, picoIndex_t* smoothingGroup )
2221 picoSurface_t* workSurface = NULL;
2223 /* see if a surface already has the shader */
2224 for ( i = 0 ; i < model->numSurfaces ; i++ )
2226 workSurface = model->surface[i];
2227 if ( !name || !strcmp(workSurface->name, name) )
2228 if ( workSurface->shader == shader )
2234 /* no surface uses this shader yet, so create a new surface */
2235 if ( !workSurface || i >=model->numSurfaces )
2237 /* create a new surface in the model for the unique shader */
2238 workSurface = PicoNewSurface(model);
2241 _pico_printf ( PICO_ERROR , "Could not allocate a new surface!\n" );
2245 /* do surface setup */
2246 PicoSetSurfaceType( workSurface, PICO_TRIANGLES );
2247 PicoSetSurfaceName( workSurface, name ? name : shader->name );
2248 PicoSetSurfaceShader( workSurface, shader );
2251 /* add the triangle data to the surface */
2252 for ( i = 0 ; i < 3 ; i++ )
2254 /* get the next free spot in the index array */
2255 int newVertIndex = PicoGetSurfaceNumIndexes ( workSurface );
2257 /* get the index of the vertex that we're going to store at newVertIndex */
2258 vertDataIndex = PicoFindSurfaceVertexNum ( workSurface , *xyz[i] , *normals[i] , numSTs , st[i] , numColors , colors[i], smoothingGroup[i]);
2260 /* the vertex wasn't found, so create a new vertex in the pool from the data we have */
2261 if ( vertDataIndex == -1 )
2263 /* find the next spot for a new vertex */
2264 vertDataIndex = PicoGetSurfaceNumVertexes ( workSurface );
2266 /* assign the data to it */
2267 PicoSetSurfaceXYZ ( workSurface ,vertDataIndex , *xyz[i] );
2268 PicoSetSurfaceNormal ( workSurface , vertDataIndex , *normals[i] );
2270 /* make sure to copy over all available ST's and colors for the vertex */
2271 for ( j = 0 ; j < numColors ; j++ )
2273 PicoSetSurfaceColor( workSurface , j , vertDataIndex , colors[i][j] );
2275 for ( j = 0 ; j < numSTs ; j++ )
2277 PicoSetSurfaceST ( workSurface , j , vertDataIndex , st[i][j] );
2280 PicoSetSurfaceSmoothingGroup ( workSurface , vertDataIndex , smoothingGroup[i] );
2283 /* add this vertex to the triangle */
2284 PicoSetSurfaceIndex ( workSurface , newVertIndex , vertDataIndex );