root/GtkRadiant/trunk/libs/picomodel/picomodel.c

Revision 275, 45.8 kB (checked in by mattn, 4 months ago)

* fixed warnings
* removed www dir (dead links, almost none of the posted links are available - correct me when i'm wrong, then we can revert this remove)

  • Property svn:eol-style set to native
Line 
1 /* -----------------------------------------------------------------------------
2
3 PicoModel Library
4
5 Copyright (c) 2002, Randy Reddig & seaw0lf
6 All rights reserved.
7
8 Redistribution and use in source and binary forms, with or without modification,
9 are permitted provided that the following conditions are met:
10
11 Redistributions of source code must retain the above copyright notice, this list
12 of conditions and the following disclaimer.
13
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.
17
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.
21
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.
32
33 ----------------------------------------------------------------------------- */
34
35
36
37 /* marker */
38 #define PICOMODEL_C
39
40
41
42 /* dependencies */
43 #include "picointernal.h"
44
45
46
47 /*
48 PicoInit()
49 initializes the picomodel library
50 */
51
52 int PicoInit( void )
53 {
54         /* successfully initialized -sea */
55         return 1;
56 }
57
58
59
60 /*
61 PicoShutdown()
62 shuts the pico model library down
63 */
64
65 void PicoShutdown( void )
66 {
67         /* do something interesting here in the future */
68         return;
69 }
70
71
72
73 /*
74 PicoError()
75 returns last picomodel error code (see PME_* defines)
76 */
77
78 int PicoError( void )
79 {
80         /* todo: do something here */
81         return 0;
82 }
83
84
85
86 /*
87 PicoSetMallocFunc()
88 sets the ptr to the malloc function
89 */
90
91 void PicoSetMallocFunc( void *(*func)( size_t ) )
92 {
93         if( func != NULL )
94                 _pico_ptr_malloc = func;
95 }
96
97
98
99 /*
100 PicoSetFreeFunc()
101 sets the ptr to the free function
102 */
103
104 void PicoSetFreeFunc( void (*func)( void* ) )
105 {
106         if( func != NULL )
107                 _pico_ptr_free = func;
108 }
109
110
111
112 /*
113 PicoSetLoadFileFunc()
114 sets the ptr to the file load function
115 */
116
117 void PicoSetLoadFileFunc( void (*func)( char*, unsigned char**, int* ) )
118 {
119         if( func != NULL )
120                 _pico_ptr_load_file = func;
121 }
122
123
124
125 /*
126 PicoSetFreeFileFunc()
127 sets the ptr to the free function
128 */
129
130 void PicoSetFreeFileFunc( void (*func)( void* ) )
131 {
132         if( func != NULL )
133                 _pico_ptr_free_file = func;
134 }
135
136
137
138 /*
139 PicoSetPrintFunc()
140 sets the ptr to the print function
141 */
142
143 void PicoSetPrintFunc( void (*func)( int, const char* ) )
144 {
145         if( func != NULL )
146                 _pico_ptr_print = func;
147 }
148
149
150
151 /*
152 PicoLoadModel()
153 the meat and potatoes function
154 */
155
156 picoModel_t     *PicoLoadModel( char *fileName, int frameNum )
157 {
158         const picoModule_t      **modules, *pm;
159         picoModel_t                     *model;
160         picoByte_t                      *buffer;
161         int                                     bufSize;
162         char                            *modelFileName, *remapFileName;
163
164
165         /* init */
166         model = NULL;
167
168         /* make sure we've got a file name */
169         if( fileName == NULL )
170         {
171                 _pico_printf( PICO_ERROR, "PicoLoadModel: No filename given (fileName == NULL)" );
172                 return NULL;
173         }
174
175         /* load file data (buffer is allocated by host app) */
176         _pico_load_file( fileName, &buffer, &bufSize );
177         if( bufSize < 0 )
178         {
179                 _pico_printf( PICO_ERROR, "PicoLoadModel: Failed loading model %s", fileName );
180                 return NULL;
181         }
182
183         /* get ptr to list of supported modules */
184         modules = PicoModuleList( NULL );
185
186         /* run it through the various loader functions and try */
187         /* to find a loader that fits the given file data */
188         for( ; *modules != NULL; modules++ )
189         {
190                 /* get module */
191                 pm = *modules;
192
193                 /* sanity check */
194                 if( pm == NULL)
195                         break;
196
197                 /* module must be able to load */
198                 if( pm->canload == NULL || pm->load == NULL )
199                         continue;
200
201                 /* see whether this module can load the model file or not */
202                 if( pm->canload( fileName, buffer, bufSize ) == PICO_PMV_OK )
203                 {
204                         /* use loader provided by module to read the model data */
205                         model = pm->load( fileName, frameNum, buffer, bufSize );
206                         if( model == NULL )
207                         {
208                                 _pico_free_file( buffer );
209                                 return NULL;
210                         }
211
212                         /* assign pointer to file format module */
213                         model->module = pm;
214
215                         /* get model file name */
216                         modelFileName = PicoGetModelFileName( model );
217
218                         /* apply model remappings from <model>.remap */
219                         if( strlen( modelFileName ) )
220                         {
221                                 /* alloc copy of model file name */
222                                 remapFileName = _pico_alloc( strlen( modelFileName ) + 20 );
223                                 if( remapFileName != NULL )
224                                 {
225                                         /* copy model file name and change extension */
226                                         strcpy( remapFileName, modelFileName );
227                                         _pico_setfext( remapFileName, "remap" );
228
229                                         /* try to remap model; we don't handle the result */
230                                         PicoRemapModel( model, remapFileName );
231
232                                         /* free the remap file name string */
233                                         _pico_free( remapFileName );
234                                 }
235                         }
236
237                         /* model was loaded, so break out of loop */
238                         break;
239                 }
240         }
241
242         /* free memory used by file buffer */
243         if( buffer)
244                 _pico_free_file( buffer );
245
246         /* return */
247         return model;
248 }
249
250
251
252 /* ----------------------------------------------------------------------------
253 models
254 ---------------------------------------------------------------------------- */
255
256 /*
257 PicoNewModel()
258 creates a new pico model
259 */
260
261 picoModel_t *PicoNewModel( void )
262 {
263         picoModel_t     *model;
264
265         /* allocate */
266         model = _pico_alloc( sizeof(picoModel_t) );
267         if( model == NULL )
268                 return NULL;
269
270         /* clear */
271         memset( model,0,sizeof(picoModel_t) );
272
273         /* model set up */
274         _pico_zero_bounds( model->mins,model->maxs );
275
276         /* set initial frame count to 1 -sea */
277         model->numFrames = 1;
278
279         /* return ptr to new model */
280         return model;
281 }
282
283
284
285 /*
286 PicoFreeModel()
287 frees a model and all associated data
288 */
289
290 void PicoFreeModel( picoModel_t *model )
291 {
292         int                             i;
293
294
295         /* sanity check */
296         if( model == NULL )
297                 return;
298
299         /* free bits */
300         if( model->name )
301                 _pico_free( model->name );
302
303         /* free shaders */
304         for( i = 0; i < model->numShaders; i++ )
305                 PicoFreeShader( model->shader[ i ] );
306         free( model->shader );
307
308         /* free surfaces */
309         for( i = 0; i < model->numSurfaces; i++ )
310                 PicoFreeSurface( model->surface[ i ] );
311         free( model->surface );
312
313         /* free the model */
314         _pico_free( model );
315 }
316
317
318
319 /*
320 PicoAdjustModel()
321 adjusts a models's memory allocations to handle the requested sizes.
322 will always grow, never shrink
323 */
324
325 int PicoAdjustModel( picoModel_t *model, int numShaders, int numSurfaces )
326 {
327         /* dummy check */
328         if( model == NULL )
329                 return 0;
330
331         /* bare minimums */
332         /* sea: null surface/shader fix (1s=>0s) */
333         if( numShaders < 0 )
334                 numShaders = 0;
335         if( numSurfaces < 0 )
336                 numSurfaces = 0;
337
338         /* additional shaders? */
339         while( numShaders > model->maxShaders )
340         {
341                 model->maxShaders += PICO_GROW_SHADERS;
342                 if( !_pico_realloc( (void *) &model->shader, model->numShaders * sizeof( *model->shader ), model->maxShaders * sizeof( *model->shader ) ) )
343                         return 0;
344         }
345
346         /* set shader count to higher */
347         if( numShaders > model->numShaders )
348                 model->numShaders = numShaders;
349
350         /* additional surfaces? */
351         while( numSurfaces > model->maxSurfaces )
352         {
353                 model->maxSurfaces += PICO_GROW_SURFACES;
354                 if( !_pico_realloc( (void *) &model->surface, model->numSurfaces * sizeof( *model->surface ), model->maxSurfaces * sizeof( *model->surface ) ) )
355                         return 0;
356         }
357
358         /* set shader count to higher */
359         if( numSurfaces > model->numSurfaces )
360                 model->numSurfaces = numSurfaces;
361
362         /* return ok */
363         return 1;
364 }
365
366
367
368 /* ----------------------------------------------------------------------------
369 shaders
370 ---------------------------------------------------------------------------- */
371
372 /*
373 PicoNewShader()
374 creates a new pico shader and returns its index. -sea
375 */
376
377 picoShader_t *PicoNewShader( picoModel_t *model )
378 {
379         picoShader_t    *shader;
380
381
382         /* allocate and clear */
383         shader = _pico_alloc( sizeof(picoShader_t) );
384         if( shader == NULL )
385                 return NULL;
386         memset( shader, 0, sizeof(picoShader_t) );
387
388         /* attach it to the model */
389         if( model != NULL )
390         {
391                 /* adjust model */
392                 if( !PicoAdjustModel( model, model->numShaders + 1, 0 ) )
393                 {
394                         _pico_free( shader );
395                         return NULL;
396                 }
397                 /* attach */
398                 model->shader[ model->numShaders - 1 ] = shader;
399                 shader->model = model;
400         }
401         /* setup default shader colors */
402         _pico_set_color( shader->ambientColor,0,0,0,0 );
403         _pico_set_color( shader->diffuseColor,255,255,255,1 );
404         _pico_set_color( shader->specularColor,0,0,0,0 );
405
406         /* no need to do this, but i do it anyway */
407         shader->transparency = 0;
408         shader->shininess = 0;
409
410         /* return the newly created shader */
411         return shader;
412 }
413
414
415
416 /*
417 PicoFreeShader()
418 frees a shader and all associated data -sea
419 */
420
421 void PicoFreeShader( picoShader_t *shader )
422 {
423         /* dummy check */
424         if( shader == NULL )
425                 return;
426
427         /* free bits */
428         if( shader->name )
429                 _pico_free( shader->name );
430         if( shader->mapName )
431                 _pico_free( shader->mapName );
432
433         /* free the shader */
434         _pico_free( shader );
435 }
436
437
438
439 /*
440 PicoFindShader()
441 finds a named shader in a model
442 */
443
444 picoShader_t *PicoFindShader( picoModel_t *model, char *name, int caseSensitive )
445 {
446         int             i;
447
448
449         /* sanity checks */
450         if( model == NULL || name == NULL )     /* sea: null name fix */
451                 return NULL;
452
453         /* walk list */
454         for( i = 0; i < model->numShaders; i++ )
455         {
456                 /* skip null shaders or shaders with null names */
457                 if( model->shader[ i ] == NULL ||
458                         model->shader[ i ]->name == NULL )
459                         continue;
460
461                 /* compare the shader name with name we're looking for */
462                 if( caseSensitive )
463                 {
464                         if( !strcmp( name, model->shader[ i ]->name ) )
465                                 return model->shader[ i ];
466                 }
467                 else if( !_pico_stricmp( name, model->shader[ i ]->name ) )
468                                 return model->shader[ i ];
469         }
470
471         /* named shader not found */
472         return NULL;
473 }
474
475
476
477 /* ----------------------------------------------------------------------------
478 surfaces
479 ---------------------------------------------------------------------------- */
480
481 /*
482 PicoNewSurface()
483 creates a new pico surface
484 */
485
486 picoSurface_t *PicoNewSurface( picoModel_t *model )
487 {
488         picoSurface_t   *surface;
489         char surfaceName[64];
490
491         /* allocate and clear */
492         surface = _pico_alloc( sizeof( *surface ) );
493         if( surface == NULL )
494                 return NULL;
495         memset( surface, 0, sizeof( *surface ) );
496
497         /* attach it to the model */
498         if( model != NULL )
499         {
500                 /* adjust model */
501                 if( !PicoAdjustModel( model, 0, model->numSurfaces + 1 ) )
502                 {
503                         _pico_free( surface );
504                         return NULL;
505                 }
506
507                 /* attach */
508                 model->surface[ model->numSurfaces - 1 ] = surface;
509                 surface->model = model;
510
511                 /* set default name */
512                 sprintf( surfaceName, "Unnamed_%d", model->numSurfaces );
513                 PicoSetSurfaceName( surface, surfaceName );
514         }
515
516         /* return */
517         return surface;
518 }
519
520
521
522 /*
523 PicoFreeSurface()
524 frees a surface and all associated data
525 */
526 void PicoFreeSurface( picoSurface_t *surface )
527 {
528         int             i;
529
530
531         /* dummy check */
532         if( surface == NULL )
533                 return;
534
535         /* free bits */
536         _pico_free( surface->xyz );
537         _pico_free( surface->normal );
538         _pico_free( surface->index );
539         _pico_free( surface->faceNormal );
540
541         /* free arrays */
542         for( i = 0; i < surface->numSTArrays; i++ )
543                 _pico_free( surface->st[ i ] );
544         free( surface->st );
545         for( i = 0; i < surface->numColorArrays; i++ )
546                 _pico_free( surface->color[ i ] );
547         free( surface->color );
548
549         /* free the surface */
550         _pico_free( surface );
551 }
552
553
554
555 /*
556 PicoAdjustSurface()
557 adjusts a surface's memory allocations to handle the requested sizes.
558 will always grow, never shrink
559 */
560
561 int PicoAdjustSurface( picoSurface_t *surface, int numVertexes, int numSTArrays, int numColorArrays, int numIndexes, int numFaceNormals )
562 {
563         int             i;
564
565
566         /* dummy check */
567         if( surface == NULL )
568                 return 0;
569
570         /* bare minimums */
571         if( numVertexes < 1 )
572                 numVertexes = 1;
573         if( numSTArrays < 1 )
574                 numSTArrays = 1;
575         if( numColorArrays < 1 )
576                 numColorArrays = 1;
577         if( numIndexes < 1 )
578                 numIndexes = 1;
579
580         /* additional vertexes? */
581         while( numVertexes > surface->maxVertexes ) /* fix */
582         {
583                 surface->maxVertexes += PICO_GROW_VERTEXES;
584                 if( !_pico_realloc( (void *) &surface->xyz, surface->numVertexes * sizeof( *surface->xyz ), surface->maxVertexes * sizeof( *surface->xyz ) ) )
585                         return 0;
586                 if( !_pico_realloc( (void *) &surface->normal, surface->numVertexes * sizeof( *surface->normal ), surface->maxVertexes * sizeof( *surface->normal ) ) )
587                         return 0;
588                 for( i = 0; i < surface->numSTArrays; i++ )
589                         if( !_pico_realloc( (void*) &surface->st[ i ], surface->numVertexes * sizeof( *surface->st[ i ] ), surface->maxVertexes * sizeof( *surface->st[ i ] ) ) )
590                         return 0;
591                 for( i = 0; i < surface->numColorArrays; i++ )
592                         if( !_pico_realloc( (void*) &surface->color[ i ], surface->numVertexes * sizeof( *surface->color[ i ] ), surface->maxVertexes * sizeof( *surface->color[ i ] ) ) )
593                         return 0;
594         }
595
596         /* set vertex count to higher */
597         if( numVertexes > surface->numVertexes )
598                 surface->numVertexes = numVertexes;
599
600         /* additional st arrays? */
601         while( numSTArrays > surface->maxSTArrays ) /* fix */
602         {
603                 surface->maxSTArrays += PICO_GROW_ARRAYS;
604                 if( !_pico_realloc( (void*) &surface->st, surface->numSTArrays * sizeof( *surface->st ), surface->maxSTArrays * sizeof( *surface->st ) ) )
605                         return 0;
606                 while( surface->numSTArrays < numSTArrays )
607                 {
608                         surface->st[ surface->numSTArrays ] = _pico_alloc( surface->maxVertexes * sizeof( *surface->st[ 0 ] ) );
609                         memset( surface->st[ surface->numSTArrays ], 0, surface->maxVertexes * sizeof( *surface->st[ 0 ] ) );
610                         surface->numSTArrays++;
611                 }
612         }
613
614         /* additional color arrays? */
615         while( numColorArrays > surface->maxColorArrays ) /* fix */
616         {
617                 surface->maxColorArrays += PICO_GROW_ARRAYS;
618                 if( !_pico_realloc( (void*) &surface->color, surface->numColorArrays * sizeof( *surface->color ), surface->maxColorArrays * sizeof( *surface->color ) ) )
619                         return 0;
620                 while( surface->numColorArrays < numColorArrays )
621                 {
622                         surface->color[ surface->numColorArrays ] = _pico_alloc( surface->maxVertexes * sizeof( *surface->color[ 0 ] ) );
623                         memset( surface->color[ surface->numColorArrays ], 0, surface->maxVertexes * sizeof( *surface->color[ 0 ] ) );
624                         surface->numColorArrays++;
625                 }
626         }
627
628         /* additional indexes? */
629         while( numIndexes > surface->maxIndexes ) /* fix */
630         {
631                 surface->maxIndexes += PICO_GROW_INDEXES;
632                 if( !_pico_realloc( (void*) &surface->index, surface->numIndexes * sizeof( *surface->index ), surface->maxIndexes * sizeof( *surface->index ) ) )
633                         return 0;
634         }
635
636         /* set index count to higher */
637         if( numIndexes > surface->numIndexes )
638                 surface->numIndexes = numIndexes;
639
640         /* additional face normals? */
641         while( numFaceNormals > surface->maxFaceNormals ) /* fix */
642         {
643                 surface->maxFaceNormals += PICO_GROW_FACES;
644                 if( !_pico_realloc( (void *) &surface->faceNormal, surface->numFaceNormals * sizeof( *surface->faceNormal ), surface->maxFaceNormals * sizeof( *surface->faceNormal ) ) )
645                         return 0;
646         }
647
648         /* set face normal count to higher */
649         if( numFaceNormals > surface->numFaceNormals )
650                 surface->numFaceNormals = numFaceNormals;
651
652         /* return ok */
653         return 1;
654 }
655
656
657 /* PicoFindSurface:
658  *   Finds first matching named surface in a model.
659  */
660 picoSurface_t *PicoFindSurface(
661         picoModel_t *model, char *name, int caseSensitive )
662 {
663         int             i;
664
665         /* sanity check */
666         if( model == NULL || name == NULL )
667                 return NULL;
668
669         /* walk list */
670         for( i = 0; i < model->numSurfaces; i++ )
671         {
672                 /* skip null surfaces or surfaces with null names */
673                 if( model->surface[ i ] == NULL ||
674                         model->surface[ i ]->name == NULL )
675                         continue;
676
677                 /* compare the surface name with name we're looking for */
678                 if (caseSensitive) {
679                         if( !strcmp(name,model->surface[ i ]->name) )
680                                 return model->surface[ i ];
681                 } else {
682                         if( !_pico_stricmp(name,model->surface[ i ]->name) )
683                                 return model->surface[ i ];
684                 }
685         }
686         /* named surface not found */
687         return NULL;
688 }
689
690
691
692 /*----------------------------------------------------------------------------
693   PicoSet*() Setter Functions
694 ----------------------------------------------------------------------------*/
695
696 void PicoSetModelName( picoModel_t *model, char *name )
697 {
698         if( model == NULL || name == NULL )
699                 return;
700         if( model->name != NULL )
701                 _pico_free( model->name );
702
703         model->name = _pico_clone_alloc( name,-1 );
704 }
705
706
707
708 void PicoSetModelFileName( picoModel_t *model, char *fileName )
709 {
710         if( model == NULL || fileName == NULL )
711                 return;
712         if( model->fileName != NULL )
713                 _pico_free( model->fileName );
714
715         model->fileName = _pico_clone_alloc( fileName,-1 );
716 }
717
718
719
720 void PicoSetModelFrameNum( picoModel_t *model, int frameNum )
721 {
722         if( model == NULL )
723                 return;
724         model->frameNum = frameNum;
725 }
726
727
728
729 void PicoSetModelNumFrames( picoModel_t *model, int numFrames )
730 {
731         if( model == NULL )
732                 return;
733         model->numFrames = numFrames;
734 }
735
736
737
738 void PicoSetModelData( picoModel_t *model, void *data )
739 {
740         if( model == NULL )
741                 return;
742         model->data = data;
743 }
744
745
746
747 void PicoSetShaderName( picoShader_t *shader, char *name )
748 {
749         if( shader == NULL || name == NULL )
750                 return;
751         if( shader->name != NULL )
752                 _pico_free( shader->name );
753
754         shader->name = _pico_clone_alloc( name,-1 );
755 }
756
757
758
759 void PicoSetShaderMapName( picoShader_t *shader, char *mapName )
760 {
761         if( shader == NULL || mapName == NULL )
762                 return;
763         if( shader->mapName != NULL )
764                 _pico_free( shader->mapName );
765
766         shader->mapName = _pico_clone_alloc( mapName,-1 );
767 }
768
769
770
771 void PicoSetShaderAmbientColor( picoShader_t *shader, picoColor_t color )
772 {
773         if( shader == NULL || color == NULL )
774                 return;
775         shader->ambientColor[ 0 ] = color[ 0 ];
776         shader->ambientColor[ 1 ] = color[ 1 ];
777         shader->ambientColor[ 2 ] = color[ 2 ];
778         shader->ambientColor[ 3 ] = color[ 3 ];
779 }
780
781
782
783 void PicoSetShaderDiffuseColor( picoShader_t *shader, picoColor_t color )
784 {
785         if( shader == NULL || color == NULL )
786                 return;
787         shader->diffuseColor[ 0 ] = color[ 0 ];
788         shader->diffuseColor[ 1 ] = color[ 1 ];
789         shader->diffuseColor[ 2 ] = color[ 2 ];
790         shader->diffuseColor[ 3 ] = color[ 3 ];
791 }
792
793
794
795 void PicoSetShaderSpecularColor( picoShader_t *shader, picoColor_t color )
796 {
797         if( shader == NULL || color == NULL )
798                 return;
799         shader->specularColor[ 0 ] = color[ 0 ];
800         shader->specularColor[ 1 ] = color[ 1 ];
801         shader->specularColor[ 2 ] = color[ 2 ];
802         shader->specularColor[ 3 ] = color[ 3 ];
803 }
804
805
806
807 void PicoSetShaderTransparency( picoShader_t *shader, float value )
808 {
809         if( shader == NULL )
810                 return;
811         shader->transparency = value;
812
813         /* cap to 0..1 range */
814         if (shader->transparency < 0.0)
815                 shader->transparency = 0.0;
816         if (shader->transparency > 1.0)
817                 shader->transparency = 1.0;
818 }
819
820
821
822 void PicoSetShaderShininess( picoShader_t *shader, float value )
823 {
824         if( shader == NULL )
825                 return;
826         shader->shininess = value;
827
828         /* cap to 0..127 range */
829         if (shader->shininess < 0.0)
830                 shader->shininess = 0.0;
831         if (shader->shininess > 127.0)
832                 shader->shininess = 127.0;
833 }
834
835
836
837 void PicoSetSurfaceData( picoSurface_t *surface, void *data )
838 {
839         if( surface == NULL )
840                 return;
841         surface->data = data;
842 }
843
844
845
846 void PicoSetSurfaceType( picoSurface_t *surface, picoSurfaceType_t type )
847 {
848         if( surface == NULL )
849                 return;
850         surface->type = type;
851 }
852
853
854
855 void PicoSetSurfaceName( picoSurface_t *surface, char *name )
856 {
857         if( surface == NULL || name == NULL )
858                 return;
859         if( surface->name != NULL )
860                 _pico_free( surface->name );
861
862         surface->name = _pico_clone_alloc( name,-1 );
863 }
864
865
866
867 void PicoSetSurfaceShader( picoSurface_t *surface, picoShader_t *shader )
868 {
869         if( surface == NULL )
870                 return;
871         surface->shader = shader;
872 }
873
874
875
876 void PicoSetSurfaceXYZ( picoSurface_t *surface, int num, picoVec3_t xyz )
877 {
878         if( surface == NULL || num < 0 || xyz == NULL )
879                 return;
880         if( !PicoAdjustSurface( surface, num + 1, 0, 0, 0, 0 ) )
881                 return;
882         _pico_copy_vec( xyz, surface->xyz[ num ] );
883         if( surface->model != NULL )
884                 _pico_expand_bounds( xyz, surface->model->mins, surface->model->maxs );
885 }
886
887
888
889 void PicoSetSurfaceNormal( picoSurface_t *surface, int num, picoVec3_t normal )
890 {
891         if( surface == NULL || num < 0 || normal == NULL )
892                 return;
893         if( !PicoAdjustSurface( surface, num + 1, 0, 0, 0, 0 ) )
894                 return;
895         _pico_copy_vec( normal, surface->normal[ num ] );
896 }
897
898
899
900 void PicoSetSurfaceST( picoSurface_t *surface, int array, int num, picoVec2_t st )
901 {
902         if( surface == NULL || num < 0 || st == NULL )
903                 return;
904         if( !PicoAdjustSurface( surface, num + 1, array + 1, 0, 0, 0 ) )
905                 return;
906         surface->st[ array ][ num ][ 0 ] = st[ 0 ];
907         surface->st[ array ][ num ][ 1 ] = st[ 1 ];
908 }
909
910
911
912 void PicoSetSurfaceColor( picoSurface_t *surface, int array, int num, picoColor_t color )
913 {
914         if( surface == NULL || num < 0 || color == NULL )
915                 return;
916         if( !PicoAdjustSurface( surface, num + 1, 0, array + 1, 0, 0 ) )
917                 return;
918         surface->color[ array ][ num ][ 0 ] = color[ 0 ];
919         surface->color[ array ][ num ][ 1 ] = color[ 1 ];
920         surface->color[ array ][ num ][ 2 ] = color[ 2 ];
921         surface->color[ array ][ num ][ 3 ] = color[ 3 ];
922 }
923
924
925
926 void PicoSetSurfaceIndex( picoSurface_t *surface, int num, picoIndex_t index )
927 {
928         if( surface == NULL || num < 0 )
929                 return;
930         if( !PicoAdjustSurface( surface, 0, 0, 0, num + 1, 0 ) )
931                 return;
932         surface->index[ num ] = index;
933 }
934
935
936
937 void PicoSetSurfaceIndexes( picoSurface_t *surface, int num, picoIndex_t *index, int count )
938 {
939         if( num < 0 || index == NULL || count < 1 )
940                 return;
941         if( !PicoAdjustSurface( surface, 0, 0, 0, num + count, 0 ) )
942                 return;
943         memcpy( &surface->index[ num ], index, count * sizeof( surface->index[ num ] ) );
944 }
945
946
947
948 void PicoSetFaceNormal( picoSurface_t *surface, int num, picoVec3_t normal )
949 {
950         if( surface == NULL || num < 0 || normal == NULL )
951                 return;
952         if( !PicoAdjustSurface( surface, 0, 0, 0, 0, num + 1 ) )
953                 return;
954         _pico_copy_vec( normal, surface->faceNormal[ num ] );
955 }
956
957