1 /* -----------------------------------------------------------------------------
\r
5 Copyright (c) 2002, Randy Reddig & seaw0lf
\r
8 Redistribution and use in source and binary forms, with or without modification,
\r
9 are permitted provided that the following conditions are met:
\r
11 Redistributions of source code must retain the above copyright notice, this list
\r
12 of conditions and the following disclaimer.
\r
14 Redistributions in binary form must reproduce the above copyright notice, this
\r
15 list of conditions and the following disclaimer in the documentation and/or
\r
16 other aseMaterialList provided with the distribution.
\r
18 Neither the names of the copyright holders nor the names of its contributors may
\r
19 be used to endorse or promote products derived from this software without
\r
20 specific prior written permission.
\r
22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
\r
23 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
\r
24 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
\r
25 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
\r
26 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
\r
27 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
\r
28 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
\r
29 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
\r
30 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
\r
31 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
33 ----------------------------------------------------------------------------- */
\r
39 /* uncomment when debugging this module */
\r
40 //#define DEBUG_PM_ASE
\r
41 //#define DEBUG_PM_ASE_EX
\r
45 #include "picointernal.h"
\r
52 static picoColor_t white = { 255, 255, 255, 255 };
\r
54 /* jhefty - multi-subobject material support */
\r
56 /* Material/SubMaterial management */
\r
57 /* A material should have 1..n submaterials assigned to it */
\r
59 typedef struct aseSubMaterial_s
\r
61 struct aseSubMaterial_s* next;
\r
63 picoShader_t* shader;
\r
67 typedef struct aseMaterial_s
\r
69 struct aseMaterial_s* next;
\r
70 struct aseSubMaterial_s* subMtls;
\r
74 /* Material/SubMaterial management functions */
\r
75 static aseMaterial_t* _ase_get_material ( aseMaterial_t* list , int mtlIdParent )
\r
77 aseMaterial_t* mtl = list;
\r
81 if ( mtlIdParent == mtl->mtlId )
\r
90 static aseSubMaterial_t* _ase_get_submaterial ( aseMaterial_t* list, int mtlIdParent , int subMtlId )
\r
92 aseMaterial_t* parent = _ase_get_material ( list , mtlIdParent );
\r
93 aseSubMaterial_t* subMtl = NULL;
\r
97 _pico_printf ( PICO_ERROR , "No ASE material exists with id %i\n" , mtlIdParent );
\r
101 subMtl = parent->subMtls;
\r
104 if ( subMtlId == subMtl->subMtlId )
\r
108 subMtl = subMtl->next;
\r
113 static aseMaterial_t* _ase_add_material( aseMaterial_t **list, int mtlIdParent )
\r
115 aseMaterial_t *mtl = _pico_calloc( 1, sizeof( aseMaterial_t ) );
\r
116 mtl->mtlId = mtlIdParent;
\r
117 mtl->subMtls = NULL;
\r
124 static aseSubMaterial_t* _ase_add_submaterial( aseMaterial_t **list, int mtlIdParent, int subMtlId, picoShader_t* shader )
\r
126 aseMaterial_t *parent = _ase_get_material( *list, mtlIdParent );
\r
127 aseSubMaterial_t *subMtl = _pico_calloc( 1, sizeof ( aseSubMaterial_t ) );
\r
131 parent = _ase_add_material ( list , mtlIdParent );
\r
134 subMtl->shader = shader;
\r
135 subMtl->subMtlId = subMtlId;
\r
136 subMtl->next = parent->subMtls;
\r
137 parent->subMtls = subMtl;
\r
142 static void _ase_free_materials( aseMaterial_t **list )
\r
144 aseMaterial_t* mtl = *list;
\r
145 aseSubMaterial_t* subMtl = NULL;
\r
147 aseMaterial_t* mtlTemp = NULL;
\r
148 aseSubMaterial_t* subMtlTemp = NULL;
\r
152 subMtl = mtl->subMtls;
\r
155 subMtlTemp = subMtl->next;
\r
156 _pico_free ( subMtl );
\r
157 subMtl = subMtlTemp;
\r
159 mtlTemp = mtl->next;
\r
160 _pico_free ( mtl );
\r
166 #ifdef DEBUG_PM_ASE
\r
167 static void _ase_print_materials( aseMaterial_t *list )
\r
169 aseMaterial_t* mtl = list;
\r
170 aseSubMaterial_t* subMtl = NULL;
\r
174 _pico_printf ( PICO_NORMAL , "ASE Material %i" , mtl->mtlId );
\r
175 subMtl = mtl->subMtls;
\r
178 _pico_printf ( PICO_NORMAL , " -- ASE SubMaterial %i - %s\n" , subMtl->subMtlId , subMtl->shader->name );
\r
179 subMtl = subMtl->next;
\r
184 #endif //DEBUG_PM_ASE
\r
186 /* ASE Face management */
\r
187 /* These are used to keep an association between a submaterial and a face definition */
\r
188 /* They are kept in parallel with the current picoSurface, */
\r
189 /* and are used by _ase_submit_triangles to lookup the proper material/submaterial IDs */
\r
190 typedef struct aseFace_s
\r
192 struct aseFace_s* next;
\r
198 /* ASE Face management functions */
\r
199 void _ase_add_face( aseFace_t **list, aseFace_t **tail, aseFace_t *newFace )
\r
201 aseFace_t* face = *list;
\r
202 aseFace_t* tempFace = NULL;
\r
204 /* insert as head of list */
\r
211 (*tail)->next = newFace;
\r
215 newFace->next = NULL;
\r
217 //tag the color indices so we can detect them and apply the default color to them
\r
218 newFace->index[6] = -1;
\r
219 newFace->index[7] = -1;
\r
220 newFace->index[8] = -1;
\r
223 aseFace_t* _ase_get_face_for_index( aseFace_t *list, int index )
\r
226 aseFace_t* face = list;
\r
228 while ( counter < index )
\r
235 static void _ase_free_faces (aseFace_t** list, aseFace_t** tail )
\r
237 aseFace_t* face = *list;
\r
238 aseFace_t* tempFace = NULL;
\r
242 tempFace = face->next;
\r
243 _pico_free ( face );
\r
252 * - apply material specific uv offsets to uv coordinates
\r
256 * validates a 3dsmax ase model file.
\r
258 static int _ase_canload( PM_PARAMS_CANLOAD )
\r
263 /* quick data length validation */
\r
265 return PICO_PMV_ERROR_SIZE;
\r
267 /* keep the friggin compiler happy */
\r
268 *fileName = *fileName;
\r
270 /* create pico parser */
\r
271 p = _pico_new_parser( (picoByte_t*) buffer, bufSize );
\r
273 return PICO_PMV_ERROR_MEMORY;
\r
275 /* get first token */
\r
276 if( _pico_parse_first( p ) == NULL)
\r
278 return PICO_PMV_ERROR_IDENT;
\r
281 /* check first token */
\r
282 if( _pico_stricmp( p->token, "*3dsmax_asciiexport" ) )
\r
284 _pico_free_parser( p );
\r
285 return PICO_PMV_ERROR_IDENT;
\r
288 /* free the pico parser object */
\r
289 _pico_free_parser( p );
\r
291 /* file seems to be a valid ase file */
\r
292 return PICO_PMV_OK;
\r
297 /* _ase_submit_triangles - jhefty
\r
298 use the surface and the current face list to look up material/submaterial IDs
\r
299 and submit them to the model for proper processing
\r
301 The following still holds from ydnar's _ase_make_surface:
\r
302 indexes 0 1 2 = vert indexes
\r
303 indexes 3 4 5 = st indexes
\r
304 indexes 6 7 8 = color indexes (new)
\r
307 static void _ase_submit_triangles ( picoSurface_t* surface , picoModel_t* model , aseMaterial_t* materials , aseFace_t* faces )
\r
310 aseSubMaterial_t* subMtl;
\r
311 picoVec3_t* xyz[3];
\r
312 picoVec3_t* normal[3];
\r
314 picoColor_t* color[3];
\r
318 while ( face != NULL )
\r
320 /* look up the shader for the material/submaterial pair */
\r
321 subMtl = _ase_get_submaterial( materials, face->mtlId, face->subMtlId );
\r
322 if( subMtl == NULL )
\r
324 /* ydnar: trying default submaterial */
\r
325 subMtl = _ase_get_submaterial( materials, face->mtlId, 0 );
\r
326 if( subMtl == NULL )
\r
328 _pico_printf( PICO_ERROR, "Could not find material/submaterial for id %d/%d\n", face->mtlId, face->subMtlId );
\r
333 /* we pull the data from the surface using the facelist data */
\r
334 for ( i = 0 ; i < 3 ; i ++ )
\r
336 xyz[i] = (picoVec3_t*) PicoGetSurfaceXYZ ( surface, face->index[ i ] );
\r
337 normal[i] = (picoVec3_t*) PicoGetSurfaceNormal( surface, face->index[ i ] );
\r
338 st[i] = (picoVec2_t*) PicoGetSurfaceST ( surface, 0, face->index[ i + 3 ] );
\r
340 if ( face->index [ i + 6] >= 0 )
\r
342 color[i] = (picoColor_t*)PicoGetSurfaceColor ( surface, 0, face->index[ i + 6 ] );
\r
351 /* submit the triangle to the model */
\r
352 PicoAddTriangleToModel ( model , xyz , normal , 1 , st , 1 , color , subMtl->shader );
\r
354 /* advance to the next face */
\r
355 face = face->next;
\r
360 * loads a 3dsmax ase model file.
\r
362 static picoModel_t *_ase_load( PM_PARAMS_LOAD )
\r
364 picoModel_t *model;
\r
365 picoSurface_t *surface = NULL;
\r
367 char lastNodeName[ 1024 ];
\r
369 aseFace_t* faces = NULL;
\r
370 aseFace_t* facesTail = NULL;
\r
371 aseMaterial_t* materials = NULL;
\r
373 #ifdef DEBUG_PM_ASE
\r
374 clock_t start, finish;
\r
380 #define _ase_error_return(m) \
\r
382 _pico_printf( PICO_ERROR,"%s in ASE, line %d.",m,p->curLine); \
\r
383 _pico_free_parser( p ); \
\r
384 PicoFreeModel( model ); \
\r
387 /* create a new pico parser */
\r
388 p = _pico_new_parser( (picoByte_t *)buffer,bufSize );
\r
389 if (p == NULL) return NULL;
\r
391 /* create a new pico model */
\r
392 model = PicoNewModel();
\r
395 _pico_free_parser( p );
\r
398 /* do model setup */
\r
399 PicoSetModelFrameNum( model, frameNum );
\r
400 PicoSetModelName( model, fileName );
\r
401 PicoSetModelFileName( model, fileName );
\r
403 /* initialize some stuff */
\r
404 memset( lastNodeName,0,sizeof(lastNodeName) );
\r
406 /* parse ase model file */
\r
409 /* get first token on line */
\r
410 if (_pico_parse_first( p ) == NULL)
\r
413 /* we just skip empty lines */
\r
414 if (p->token == NULL || !strlen( p->token ))
\r
417 /* we skip invalid ase statements */
\r
418 if (p->token[0] != '*' && p->token[0] != '{' && p->token[0] != '}')
\r
420 _pico_parse_skip_rest( p );
\r
423 /* remember node name */
\r
424 if (!_pico_stricmp(p->token,"*node_name"))
\r
426 /* read node name */
\r
427 char *ptr = _pico_parse( p,0 );
\r
429 _ase_error_return("Node name parse error");
\r
431 /* remember node name */
\r
432 strncpy( lastNodeName,ptr,sizeof(lastNodeName) );
\r
434 /* model mesh (originally contained within geomobject) */
\r
435 else if (!_pico_stricmp(p->token,"*mesh"))
\r
437 /* finish existing surface */
\r
438 //_ase_make_surface( model, &surface );
\r
439 _ase_submit_triangles (surface, model ,materials,faces);
\r
440 _ase_free_faces (&faces,&facesTail);
\r
442 /* allocate new pico surface */
\r
443 surface = PicoNewSurface( NULL );
\r
444 if (surface == NULL)
\r
446 PicoFreeModel( model );
\r
450 /* mesh material reference. this usually comes at the end of */
\r
451 /* geomobjects after the mesh blocks. we must assume that the */
\r
452 /* new mesh was already created so all we can do here is assign */
\r
453 /* the material reference id (shader index) now. */
\r
454 else if (!_pico_stricmp(p->token,"*material_ref"))
\r
459 /* we must have a valid surface */
\r
460 if( surface == NULL )
\r
461 _ase_error_return("Missing mesh for material reference");
\r
463 /* get the material ref (0..n) */
\r
464 if (!_pico_parse_int( p,&mtlId) )
\r
465 _ase_error_return("Missing material reference ID");
\r
467 /* fix up all of the aseFaceList in the surface to point to the parent material */
\r
468 /* we've already saved off their subMtl */
\r
470 while ( face != NULL )
\r
472 face->mtlId = mtlId;
\r
476 /* model mesh vertex */
\r
477 else if (!_pico_stricmp(p->token,"*mesh_vertex"))
\r
482 /* we must have a valid surface */
\r
483 if( surface == NULL )
\r
486 /* get vertex data (orig: index +y -x +z) */
\r
487 if (!_pico_parse_int( p,&index ))
\r
488 _ase_error_return("Vertex parse error");
\r
489 if (!_pico_parse_vec( p,v ))
\r
490 _ase_error_return("Vertex parse error");
\r
493 PicoSetSurfaceXYZ( surface,index,v );
\r
495 /* model mesh vertex normal */
\r
496 else if (!_pico_stricmp(p->token,"*mesh_vertexnormal"))
\r
501 /* we must have a valid surface */
\r
502 if( surface == NULL )
\r
505 /* get vertex data (orig: index +y -x +z) */
\r
506 if (!_pico_parse_int( p,&index ))
\r
507 _ase_error_return("Vertex parse error");
\r
508 if (!_pico_parse_vec( p,v ))
\r
509 _ase_error_return("Vertex parse error");
\r
512 PicoSetSurfaceNormal( surface,index,v );
\r
514 /* model mesh face */
\r
515 else if (!_pico_stricmp(p->token,"*mesh_face"))
\r
517 picoIndex_t indexes[3];
\r
520 /* we must have a valid surface */
\r
521 if( surface == NULL )
\r
524 /* get face index */
\r
525 if (!_pico_parse_int( p,&index ))
\r
526 _ase_error_return("Face parse error");
\r
528 /* get 1st vertex index */
\r
529 _pico_parse( p,0 );
\r
530 if (!_pico_parse_int( p,&indexes[0] ))
\r
531 _ase_error_return("Face parse error");
\r
533 /* get 2nd vertex index */
\r
534 _pico_parse( p,0 );
\r
535 if (!_pico_parse_int( p,&indexes[1] ))
\r
536 _ase_error_return("Face parse error");
\r
538 /* get 3rd vertex index */
\r
539 _pico_parse( p,0 );
\r
540 if (!_pico_parse_int( p,&indexes[2] ))
\r
541 _ase_error_return("Face parse error");
\r
543 /* set face indexes (note interleaved offset!) */
\r
544 PicoSetSurfaceIndex( surface, (index * 9 + 0), indexes[2] );
\r
545 PicoSetSurfaceIndex( surface, (index * 9 + 1), indexes[1] );
\r
546 PicoSetSurfaceIndex( surface, (index * 9 + 2), indexes[0] );
\r
548 /* parse to the subMaterial ID */
\r
552 if (!_pico_stricmp (p->token,"*MESH_MTLID" ))
\r
554 aseFace_t* newFace;
\r
557 _pico_parse_int ( p , &subMtlId );
\r
558 newFace = _pico_calloc ( 1 , sizeof ( aseFace_t ));
\r
560 /* we fix up the mtlId later when we parse the material_ref */
\r
561 newFace->mtlId = 0;
\r
562 newFace->subMtlId = subMtlId;
\r
563 newFace->index[0] = indexes[2];
\r
564 newFace->index[1] = indexes[1];
\r
565 newFace->index[2] = indexes[0];
\r
567 _ase_add_face ( &faces,&facesTail,newFace );
\r
573 /* model texture vertex */
\r
574 else if (!_pico_stricmp(p->token,"*mesh_tvert"))
\r
579 /* we must have a valid surface */
\r
580 if( surface == NULL )
\r
583 /* get uv vertex index */
\r
584 if (!_pico_parse_int( p,&index ))
\r
585 _ase_error_return("UV vertex parse error");
\r
587 /* get uv vertex s */
\r
588 if (!_pico_parse_float( p,&uv[0] ))
\r
589 _ase_error_return("UV vertex parse error");
\r
591 /* get uv vertex t */
\r
592 if (!_pico_parse_float( p,&uv[1] ))
\r
593 _ase_error_return("UV vertex parse error");
\r
595 /* ydnar: invert t */
\r
596 uv[ 1 ] = 1.0f - uv[ 1 ];
\r
598 /* set texture vertex */
\r
599 PicoSetSurfaceST( surface,0,index,uv );
\r
601 /* ydnar: model mesh texture face */
\r
602 else if( !_pico_stricmp( p->token, "*mesh_tface" ) )
\r
604 picoIndex_t indexes[3];
\r
608 /* we must have a valid surface */
\r
609 if( surface == NULL )
\r
612 /* get face index */
\r
613 if (!_pico_parse_int( p,&index ))
\r
614 _ase_error_return("Texture face parse error");
\r
616 /* get 1st vertex index */
\r
617 if (!_pico_parse_int( p,&indexes[0] ))
\r
618 _ase_error_return("Texture face parse error");
\r
620 /* get 2nd vertex index */
\r
621 if (!_pico_parse_int( p,&indexes[1] ))
\r
622 _ase_error_return("Texture face parse error");
\r
624 /* get 3rd vertex index */
\r
625 if (!_pico_parse_int( p,&indexes[2] ))
\r
626 _ase_error_return("Texture face parse error");
\r
628 /* set face indexes (note interleaved offset!) */
\r
629 PicoSetSurfaceIndex( surface, (index * 9 + 3), indexes[2] );
\r
630 PicoSetSurfaceIndex( surface, (index * 9 + 4), indexes[1] );
\r
631 PicoSetSurfaceIndex( surface, (index * 9 + 5), indexes[0] );
\r
633 face = _ase_get_face_for_index(faces,index);
\r
634 face->index[3] = indexes[2];
\r
635 face->index[4] = indexes[1];
\r
636 face->index[5] = indexes[0];
\r
638 /* model color vertex */
\r
639 else if (!_pico_stricmp(p->token,"*mesh_vertcol"))
\r
645 /* we must have a valid surface */
\r
646 if( surface == NULL )
\r
649 /* get color vertex index */
\r
650 if (!_pico_parse_int( p,&index ))
\r
651 _ase_error_return("UV vertex parse error");
\r
653 /* get R component */
\r
654 if (!_pico_parse_float( p,&colorInput ))
\r
655 _ase_error_return("color vertex parse error");
\r
656 color[0] = (picoByte_t)(colorInput * 255);
\r
658 /* get G component */
\r
659 if (!_pico_parse_float( p,&colorInput ))
\r
660 _ase_error_return("color vertex parse error");
\r
661 color[1] = (picoByte_t)(colorInput * 255);
\r
663 /* get B component */
\r
664 if (!_pico_parse_float( p,&colorInput ))
\r
665 _ase_error_return("color vertex parse error");
\r
666 color[2] = (picoByte_t)(colorInput * 255);
\r
668 /* leave alpha alone since we don't get any data from the ASE format */
\r
671 /* set texture vertex */
\r
672 PicoSetSurfaceColor( surface,0,index,color );
\r
674 /* model color face */
\r
675 else if (!_pico_stricmp(p->token,"*mesh_cface"))
\r
677 picoIndex_t indexes[3];
\r
681 /* we must have a valid surface */
\r
682 if( surface == NULL )
\r
685 /* get face index */
\r
686 if (!_pico_parse_int( p,&index ))
\r
687 _ase_error_return("Face parse error");
\r
689 /* get 1st cvertex index */
\r
690 // _pico_parse( p,0 );
\r
691 if (!_pico_parse_int( p,&indexes[0] ))
\r
692 _ase_error_return("Face parse error");
\r
694 /* get 2nd cvertex index */
\r
695 // _pico_parse( p,0 );
\r
696 if (!_pico_parse_int( p,&indexes[1] ))
\r
697 _ase_error_return("Face parse error");
\r
699 /* get 3rd cvertex index */
\r
700 // _pico_parse( p,0 );
\r
701 if (!_pico_parse_int( p,&indexes[2] ))
\r
702 _ase_error_return("Face parse error");
\r
704 /* set face indexes (note interleaved offset!) */
\r
705 PicoSetSurfaceIndex( surface, (index * 9 + 6), indexes[2] );
\r
706 PicoSetSurfaceIndex( surface, (index * 9 + 7), indexes[1] );
\r
707 PicoSetSurfaceIndex( surface, (index * 9 + 8), indexes[0] );
\r
709 face = _ase_get_face_for_index(faces,index);
\r
710 face->index[6] = indexes[2];
\r
711 face->index[7] = indexes[1];
\r
712 face->index[8] = indexes[0];
\r
714 /* model material */
\r
715 else if( !_pico_stricmp( p->token, "*material" ) )
\r
717 aseSubMaterial_t* subMaterial = NULL;
\r
718 picoShader_t *shader;
\r
719 int level = 1, index;
\r
720 char materialName[ 1024 ];
\r
721 float transValue = 0.0f, shineValue = 1.0f;
\r
722 picoColor_t ambientColor, diffuseColor, specularColor;
\r
723 char *mapname = NULL;
\r
724 int subMtlId, subMaterialLevel = -1;
\r
727 /* get material index */
\r
728 _pico_parse_int( p,&index );
\r
731 if (!_pico_parse_check(p,1,"{"))
\r
732 _ase_error_return("Material missing opening brace");
\r
734 /* parse material block */
\r
737 /* get next token */
\r
738 if (_pico_parse(p,1) == NULL) break;
\r
739 if (!strlen(p->token)) continue;
\r
741 /* handle levels */
\r
742 if (p->token[0] == '{') level++;
\r
743 if (p->token[0] == '}') level--;
\r
746 if( level == subMaterialLevel )
\r
748 /* set material name */
\r
749 PicoSetShaderName( shader, materialName);
\r
751 /* set shader's transparency */
\r
752 PicoSetShaderTransparency( shader,transValue );
\r
754 /* set shader's ambient color */
\r
755 PicoSetShaderAmbientColor( shader,ambientColor );
\r
757 /* set diffuse alpha to transparency */
\r
758 diffuseColor[3] = (picoByte_t)( transValue * 255.0 );
\r
760 /* set shader's diffuse color */
\r
761 PicoSetShaderDiffuseColor( shader,diffuseColor );
\r
763 /* set shader's specular color */
\r
764 PicoSetShaderSpecularColor( shader,specularColor );
\r
766 /* set shader's shininess */
\r
767 PicoSetShaderShininess( shader,shineValue );
\r
769 /* set material map name */
\r
770 PicoSetShaderMapName( shader, mapname );
\r
772 subMaterial = _ase_add_submaterial( &materials, index, subMtlId, shader );
\r
773 subMaterialLevel = -1;
\r
776 /* parse submaterial index */
\r
777 if (!_pico_stricmp(p->token,"*submaterial"))
\r
779 /* allocate new pico shader */
\r
780 _pico_parse_int( p , &subMtlId );
\r
782 shader = PicoNewShader( model );
\r
783 if (shader == NULL)
\r
785 PicoFreeModel( model );
\r
788 subMaterialLevel = level;
\r
790 /* parse material name */
\r
791 else if (!_pico_stricmp(p->token,"*material_name"))
\r
793 char* name = _pico_parse(p,0);
\r
795 _ase_error_return("Missing material name");
\r
797 strcpy ( materialName , name );
\r
798 /* skip rest and continue with next token */
\r
799 _pico_parse_skip_rest( p );
\r
802 /* parse material transparency */
\r
803 else if (!_pico_stricmp(p->token,"*material_transparency"))
\r
805 /* get transparency value from ase */
\r
806 if (!_pico_parse_float( p,&transValue ))
\r
807 _ase_error_return("Material transparency parse error");
\r
809 /* skip rest and continue with next token */
\r
810 _pico_parse_skip_rest( p );
\r
813 /* parse material shininess */
\r
814 else if (!_pico_stricmp(p->token,"*material_shine"))
\r
817 * - not sure but instead of '*material_shine' i might
\r
818 * need to use '*material_shinestrength' */
\r
820 /* get shine value from ase */
\r
821 if (!_pico_parse_float( p,&shineValue ))
\r
822 _ase_error_return("Material shine parse error");
\r
824 /* scale ase shine range 0..1 to pico range 0..127 */
\r
825 shineValue *= 128.0;
\r
827 /* skip rest and continue with next token */
\r
828 _pico_parse_skip_rest( p );
\r
831 /* parse ambient material color */
\r
832 else if (!_pico_stricmp(p->token,"*material_ambient"))
\r
835 /* get r,g,b float values from ase */
\r
836 if (!_pico_parse_vec( p,vec ))
\r
837 _ase_error_return("Material color parse error");
\r
839 /* setup 0..255 range color values */
\r
840 ambientColor[ 0 ] = (int)( vec[ 0 ] * 255.0 );
\r
841 ambientColor[ 1 ] = (int)( vec[ 1 ] * 255.0 );
\r
842 ambientColor[ 2 ] = (int)( vec[ 2 ] * 255.0 );
\r
843 ambientColor[ 3 ] = (int)( 255 );
\r
845 /* skip rest and continue with next token */
\r
846 _pico_parse_skip_rest( p );
\r
849 /* parse diffuse material color */
\r
850 else if (!_pico_stricmp(p->token,"*material_diffuse"))
\r
854 /* get r,g,b float values from ase */
\r
855 if (!_pico_parse_vec( p,vec ))
\r
856 _ase_error_return("Material color parse error");
\r
858 /* setup 0..255 range color */
\r
859 diffuseColor[ 0 ] = (int)( vec[ 0 ] * 255.0 );
\r
860 diffuseColor[ 1 ] = (int)( vec[ 1 ] * 255.0 );
\r
861 diffuseColor[ 2 ] = (int)( vec[ 2 ] * 255.0 );
\r
862 diffuseColor[ 3 ] = (int)( 255 );
\r
864 /* skip rest and continue with next token */
\r
865 _pico_parse_skip_rest( p );
\r
868 /* parse specular material color */
\r
869 else if (!_pico_stricmp(p->token,"*material_specular"))
\r
873 /* get r,g,b float values from ase */
\r
874 if (!_pico_parse_vec( p,vec ))
\r
875 _ase_error_return("Material color parse error");
\r
877 /* setup 0..255 range color */
\r
878 specularColor[ 0 ] = (int)( vec[ 0 ] * 255 );
\r
879 specularColor[ 1 ] = (int)( vec[ 1 ] * 255 );
\r
880 specularColor[ 2 ] = (int)( vec[ 2 ] * 255 );
\r
881 specularColor[ 3 ] = (int)( 255 );
\r
883 /* skip rest and continue with next token */
\r
884 _pico_parse_skip_rest( p );
\r
887 /* material diffuse map */
\r
888 else if (!_pico_stricmp(p->token,"*map_diffuse") )
\r
892 /* parse material block */
\r
895 /* get next token */
\r
896 if (_pico_parse(p,1) == NULL) break;
\r
897 if (!strlen(p->token)) continue;
\r
899 /* handle levels */
\r
900 if (p->token[0] == '{') sublevel++;
\r
901 if (p->token[0] == '}') sublevel--;
\r
902 if (!sublevel) break;
\r
904 /* parse diffuse map bitmap */
\r
905 if (!_pico_stricmp(p->token,"*bitmap"))
\r
907 char* name = _pico_parse(p,0);
\r
909 _ase_error_return("Missing material map bitmap name");
\r
910 mapname = _pico_alloc ( strlen ( name ) + 1 );
\r
911 strcpy ( mapname, name );
\r
912 /* skip rest and continue with next token */
\r
913 _pico_parse_skip_rest( p );
\r
918 /* end map_diffuse block */
\r
920 /* end material block */
\r
922 if( subMaterial == NULL )
\r
924 /* allocate new pico shader */
\r
925 shader = PicoNewShader( model );
\r
926 if (shader == NULL)
\r
928 PicoFreeModel( model );
\r
932 /* set material name */
\r
933 PicoSetShaderName( shader,materialName );
\r
935 /* set shader's transparency */
\r
936 PicoSetShaderTransparency( shader,transValue );
\r
938 /* set shader's ambient color */
\r
939 PicoSetShaderAmbientColor( shader,ambientColor );
\r
941 /* set diffuse alpha to transparency */
\r
942 diffuseColor[3] = (picoByte_t)( transValue * 255.0 );
\r
944 /* set shader's diffuse color */
\r
945 PicoSetShaderDiffuseColor( shader,diffuseColor );
\r
947 /* set shader's specular color */
\r
948 PicoSetShaderSpecularColor( shader,specularColor );
\r
950 /* set shader's shininess */
\r
951 PicoSetShaderShininess( shader,shineValue );
\r
953 /* set material map name */
\r
954 PicoSetShaderMapName( shader, mapname );
\r
956 /* this is just a material with 1 submaterial */
\r
957 subMaterial = _ase_add_submaterial( &materials, index, 0, shader );
\r
960 /* ydnar: free mapname */
\r
961 if( mapname != NULL )
\r
962 _pico_free( mapname );
\r
963 } // !_pico_stricmp ( "*material" )
\r
965 /* skip unparsed rest of line and continue */
\r
966 _pico_parse_skip_rest( p );
\r
969 /* ydnar: finish existing surface */
\r
970 // _ase_make_surface( model, &surface );
\r
971 _ase_submit_triangles (surface, model ,materials,faces);
\r
972 _ase_free_faces (&faces,&facesTail);
\r
974 #ifdef DEBUG_PM_ASE
\r
975 _ase_print_materials(materials);
\r
977 elapsed = (double)(finish - start) / CLOCKS_PER_SEC;
\r
978 _pico_printf( PICO_NORMAL, "Loaded model in in %-.2f second(s)\n", elapsed );
\r
979 #endif //DEBUG_PM_ASE
\r
981 _ase_free_materials(&materials);
\r
983 /* return allocated pico model */
\r
987 /* pico file format module definition */
\r
988 const picoModule_t picoModuleASE =
\r
990 "1.0", /* module version string */
\r
991 "Autodesk 3DSMAX ASCII", /* module display name */
\r
992 "Jared Hefty, seaw0lf", /* author's name */
\r
993 "2003 Jared Hefty, 2002 seaw0lf", /* module copyright */
\r
995 "ase",NULL,NULL,NULL /* default extensions to use */
\r
997 _ase_canload, /* validation routine */
\r
998 _ase_load, /* load routine */
\r
999 NULL, /* save validation routine */
\r
1000 NULL /* save routine */
\r