pm_ase.c

Go to the documentation of this file.
00001 /* -----------------------------------------------------------------------------
00002 
00003  PicoModel Library
00004 
00005  Copyright (c) 2002, Randy Reddig & seaw0lf
00006  All rights reserved.
00007 
00008  Redistribution and use in source and binary forms, with or without modification,
00009  are permitted provided that the following conditions are met:
00010 
00011  Redistributions of source code must retain the above copyright notice, this list
00012  of conditions and the following disclaimer.
00013 
00014  Redistributions in binary form must reproduce the above copyright notice, this
00015  list of conditions and the following disclaimer in the documentation and/or
00016  other aseMaterialList provided with the distribution.
00017 
00018  Neither the names of the copyright holders nor the names of its contributors may
00019  be used to endorse or promote products derived from this software without
00020  specific prior written permission.
00021 
00022  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00023  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00024  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00025  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
00026  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00027  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
00029  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00030  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00031  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00032 
00033  ----------------------------------------------------------------------------- */
00034 
00035 /* marker */
00036 #define PM_ASE_C
00037 
00038 /* uncomment when debugging this module */
00039 /* #define DEBUG_PM_ASE */
00040 /* #define DEBUG_PM_ASE_EX */
00041 
00042 /* dependencies */
00043 #include "picointernal.h"
00044 
00045 #ifdef DEBUG_PM_ASE
00046 #include "time.h"
00047 #endif
00048 
00049 /* plain white */
00050 static picoColor_t white = { 255, 255, 255, 255 };
00051 
00052 /* jhefty - multi-subobject material support */
00053 
00054 /* Material/SubMaterial management */
00055 /* A material should have 1..n submaterials assigned to it */
00056 
00057 typedef struct aseSubMaterial_s
00058 {
00059     struct aseSubMaterial_s* next;
00060     int subMtlId;
00061     picoShader_t* shader;
00062 
00063 } aseSubMaterial_t;
00064 
00065 typedef struct aseMaterial_s
00066 {
00067     struct aseMaterial_s* next;
00068     struct aseSubMaterial_s* subMtls;
00069     int mtlId;
00070 } aseMaterial_t;
00071 
00072 /* Material/SubMaterial management functions */
00073 static aseMaterial_t* _ase_get_material (aseMaterial_t* list, int mtlIdParent)
00074 {
00075     aseMaterial_t* mtl = list;
00076 
00077     while (mtl) {
00078         if (mtlIdParent == mtl->mtlId) {
00079             break;
00080         }
00081         mtl = mtl->next;
00082     }
00083     return mtl;
00084 }
00085 
00086 static aseSubMaterial_t* _ase_get_submaterial (aseMaterial_t* list, int mtlIdParent, int subMtlId)
00087 {
00088     aseMaterial_t* parent = _ase_get_material(list, mtlIdParent);
00089     aseSubMaterial_t* subMtl = NULL;
00090 
00091     if (!parent) {
00092         _pico_printf(PICO_ERROR, "No ASE material exists with id %i\n", mtlIdParent);
00093         return NULL;
00094     }
00095 
00096     subMtl = parent->subMtls;
00097     while (subMtl) {
00098         if (subMtlId == subMtl->subMtlId) {
00099             break;
00100         }
00101         subMtl = subMtl->next;
00102     }
00103     return subMtl;
00104 }
00105 
00106 static aseSubMaterial_t* _ase_get_submaterial_or_default (aseMaterial_t* materials, int mtlIdParent, int subMtlId)
00107 {
00108     aseSubMaterial_t* subMtl = _ase_get_submaterial(materials, mtlIdParent, subMtlId);
00109     if (subMtl != NULL) {
00110         return subMtl;
00111     }
00112 
00113     /* ydnar: trying default submaterial */
00114     subMtl = _ase_get_submaterial(materials, mtlIdParent, 0);
00115     if (subMtl != NULL) {
00116         return subMtl;
00117     }
00118 
00119     _pico_printf(PICO_ERROR, "Could not find material/submaterial for id %d/%d\n", mtlIdParent, subMtlId);
00120     return NULL;
00121 }
00122 
00123 static aseMaterial_t* _ase_add_material (aseMaterial_t **list, int mtlIdParent)
00124 {
00125     aseMaterial_t *mtl = _pico_calloc(1, sizeof(aseMaterial_t));
00126     mtl->mtlId = mtlIdParent;
00127     mtl->subMtls = NULL;
00128     mtl->next = *list;
00129     *list = mtl;
00130 
00131     return mtl;
00132 }
00133 
00134 static aseSubMaterial_t* _ase_add_submaterial (aseMaterial_t **list, int mtlIdParent, int subMtlId,
00135         picoShader_t* shader)
00136 {
00137     aseMaterial_t *parent = _ase_get_material(*list, mtlIdParent);
00138     aseSubMaterial_t *subMtl = _pico_calloc(1, sizeof(aseSubMaterial_t));
00139 
00140     if (!parent) {
00141         parent = _ase_add_material(list, mtlIdParent);
00142     }
00143 
00144     subMtl->shader = shader;
00145     subMtl->subMtlId = subMtlId;
00146     subMtl->next = parent->subMtls;
00147     parent->subMtls = subMtl;
00148 
00149     return subMtl;
00150 }
00151 
00152 static void _ase_free_materials (aseMaterial_t **list)
00153 {
00154     aseMaterial_t* mtl = *list;
00155     aseSubMaterial_t* subMtl = NULL;
00156 
00157     aseMaterial_t* mtlTemp = NULL;
00158     aseSubMaterial_t* subMtlTemp = NULL;
00159 
00160     while (mtl) {
00161         subMtl = mtl->subMtls;
00162         while (subMtl) {
00163             subMtlTemp = subMtl->next;
00164             _pico_free(subMtl);
00165             subMtl = subMtlTemp;
00166         }
00167         mtlTemp = mtl->next;
00168         _pico_free(mtl);
00169         mtl = mtlTemp;
00170     }
00171     (*list) = NULL;
00172 }
00173 
00174 #ifdef DEBUG_PM_ASE
00175 static void _ase_print_materials (aseMaterial_t *list)
00176 {
00177     aseMaterial_t* mtl = list;
00178     aseSubMaterial_t* subMtl = NULL;
00179 
00180     while (mtl) {
00181         _pico_printf(PICO_NORMAL, "ASE Material %i", mtl->mtlId);
00182         subMtl = mtl->subMtls;
00183         while (subMtl) {
00184             _pico_printf(PICO_NORMAL, " -- ASE SubMaterial %i - %s\n", subMtl->subMtlId, subMtl->shader->name);
00185             subMtl = subMtl->next;
00186         }
00187         mtl = mtl->next;
00188     }
00189 }
00190 #endif
00191 
00192 /* todo:
00193  * - apply material specific uv offsets to uv coordinates
00194  */
00195 
00199 static int _ase_canload (PM_PARAMS_CANLOAD)
00200 {
00201     picoParser_t *p;
00202 
00203     /* quick data length validation */
00204     if (bufSize < 80)
00205         return PICO_PMV_ERROR_SIZE;
00206 
00207     /* create pico parser */
00208     p = _pico_new_parser((picoByte_t*) buffer, bufSize);
00209     if (p == NULL)
00210         return PICO_PMV_ERROR_MEMORY;
00211 
00212     /* get first token */
00213     if (_pico_parse_first(p) == NULL) {
00214         return PICO_PMV_ERROR_IDENT;
00215     }
00216 
00217     /* check first token */
00218     if (_pico_stricmp(p->token, "*3dsmax_asciiexport")) {
00219         _pico_free_parser(p);
00220         return PICO_PMV_ERROR_IDENT;
00221     }
00222 
00223     /* free the pico parser object */
00224     _pico_free_parser(p);
00225 
00226     /* file seems to be a valid ase file */
00227     return PICO_PMV_OK;
00228 }
00229 
00230 typedef struct aseVertex_s
00231 {
00232     picoVec3_t xyz;
00233     picoVec3_t normal;
00234     picoIndex_t id;
00235 } aseVertex_t;
00236 
00237 typedef struct aseTexCoord_s
00238 {
00239     picoVec2_t texcoord;
00240 } aseTexCoord_t;
00241 
00242 typedef struct aseColor_s
00243 {
00244     picoColor_t color;
00245 } aseColor_t;
00246 
00247 typedef struct aseFace_s
00248 {
00249     picoIndex_t indices[9];
00250     picoIndex_t smoothingGroup;
00251     picoIndex_t materialId;
00252     picoIndex_t subMaterialId;
00253 } aseFace_t;
00254 
00255 typedef aseFace_t* aseFacesIter_t;
00256 
00265 static void _ase_submit_triangles (picoModel_t* model, aseMaterial_t* materials, aseVertex_t* vertices,
00266         aseTexCoord_t* texcoords, aseColor_t* colors, aseFace_t* faces, int numFaces)
00267 {
00268     aseFacesIter_t i = faces, end = faces + numFaces;
00269     for (; i != end; ++i) {
00270         /* look up the shader for the material/submaterial pair */
00271         aseSubMaterial_t* subMtl = _ase_get_submaterial_or_default(materials, (*i).materialId, (*i).subMaterialId);
00272         if (subMtl == NULL)
00273             return;
00274 
00275         {
00276             picoVec3_t* xyz[3];
00277             picoVec3_t* normal[3];
00278             picoVec2_t* st[3];
00279             picoColor_t* color[3];
00280             picoIndex_t smooth[3];
00281             int j;
00282             /* we pull the data from the vertex, color and texcoord arrays using the face index data */
00283             for (j = 0; j < 3; j++) {
00284                 xyz[j] = &vertices[(*i).indices[j]].xyz;
00285                 normal[j] = &vertices[(*i).indices[j]].normal;
00286                 st[j] = &texcoords[(*i).indices[j + 3]].texcoord;
00287 
00288                 if (colors != NULL && (*i).indices[j + 6] >= 0) {
00289                     color[j] = &colors[(*i).indices[j + 6]].color;
00290                 } else {
00291                     color[j] = &white;
00292                 }
00293 
00294                 smooth[j] = (vertices[(*i).indices[j]].id * (1 << 16)) + (*i).smoothingGroup; /* don't merge vertices */
00295 
00296             }
00297 
00298             /* submit the triangle to the model */
00299             PicoAddTriangleToModel(model, xyz, normal, 1, st, 1, color, subMtl->shader, smooth);
00300         }
00301     }
00302 }
00303 
00304 static void shadername_convert (char* shaderName)
00305 {
00306     /* unix-style path separators */
00307     char* s = shaderName;
00308     for (; *s != '\0'; ++s) {
00309         if (*s == '\\') {
00310             *s = '/';
00311         }
00312     }
00313 }
00314 
00318 static picoModel_t *_ase_load (PM_PARAMS_LOAD)
00319 {
00320     picoModel_t *model;
00321     picoParser_t *p;
00322     char lastNodeName[1024];
00323 
00324     aseVertex_t* vertices = NULL;
00325     aseTexCoord_t* texcoords = NULL;
00326     aseColor_t* colors = NULL;
00327     aseFace_t* faces = NULL;
00328     int numVertices = 0;
00329     int numFaces = 0;
00330     int numTextureVertices = 0;
00331     int numTextureVertexFaces = 0;
00332     int numColorVertices = 0;
00333     int numColorVertexFaces = 0;
00334     int vertexId = 0;
00335 
00336     aseMaterial_t* materials = NULL;
00337 
00338 #ifdef DEBUG_PM_ASE
00339     clock_t start, finish;
00340     double elapsed;
00341     start = clock();
00342 #endif
00343 
00344     /* helper */
00345 #define _ase_error_return(m) \
00346     { \
00347         _pico_printf(PICO_ERROR, "%s in ASE, line %d.",m,p->curLine); \
00348         _pico_free_parser(p); \
00349         PicoFreeModel(model); \
00350         return NULL; \
00351     }
00352     /* create a new pico parser */
00353     p = _pico_new_parser((picoByte_t *) buffer, bufSize);
00354     if (p == NULL)
00355         return NULL;
00356 
00357     /* create a new pico model */
00358     model = PicoNewModel();
00359     if (model == NULL) {
00360         _pico_free_parser(p);
00361         return NULL;
00362     }
00363     /* do model setup */
00364     PicoSetModelFrameNum(model, frameNum);
00365     PicoSetModelName(model, fileName);
00366     PicoSetModelFileName(model, fileName);
00367 
00368     /* initialize some stuff */
00369     memset(lastNodeName, 0, sizeof(lastNodeName));
00370 
00371     /* parse ase model file */
00372     while (1) {
00373         /* get first token on line */
00374         if (_pico_parse_first(p) == NULL)
00375             break;
00376 
00377         /* we just skip empty lines */
00378         if (p->token == NULL || !strlen(p->token))
00379             continue;
00380 
00381         /* we skip invalid ase statements */
00382         if (p->token[0] != '*' && p->token[0] != '{' && p->token[0] != '}') {
00383             _pico_parse_skip_rest(p);
00384             continue;
00385         }
00386         /* remember node name */
00387         if (!_pico_stricmp(p->token, "*node_name")) {
00388             /* read node name */
00389             char *ptr = _pico_parse(p, 0);
00390             if (ptr == NULL)
00391                 _ase_error_return("Node name parse error");
00392 
00393             /* remember node name */
00394             strncpy(lastNodeName, ptr, sizeof(lastNodeName));
00395         }
00396         /* model mesh (originally contained within geomobject) */
00397         else if (!_pico_stricmp(p->token, "*mesh")) {
00398             /* finish existing surface */
00399             _ase_submit_triangles(model, materials, vertices, texcoords, colors, faces, numFaces);
00400             _pico_free(faces);
00401             _pico_free(vertices);
00402             _pico_free(texcoords);
00403             _pico_free(colors);
00404             colors = NULL; /* OrbWeaver: reset all pointers to avoid double-free */
00405             faces = NULL;
00406             vertices = NULL;
00407             texcoords = NULL;
00408         } else if (!_pico_stricmp(p->token, "*mesh_numvertex")) {
00409             if (!_pico_parse_int(p, &numVertices))
00410                 _ase_error_return("Missing MESH_NUMVERTEX value");
00411 
00412             vertices = _pico_calloc(numVertices, sizeof(aseVertex_t));
00413         } else if (!_pico_stricmp(p->token, "*mesh_numfaces")) {
00414             if (!_pico_parse_int(p, &numFaces))
00415                 _ase_error_return("Missing MESH_NUMFACES value");
00416 
00417             faces = _pico_calloc(numFaces, sizeof(aseFace_t));
00418         } else if (!_pico_stricmp(p->token, "*mesh_numtvertex")) {
00419             if (!_pico_parse_int(p, &numTextureVertices))
00420                 _ase_error_return("Missing MESH_NUMTVERTEX value");
00421 
00422             texcoords = _pico_calloc(numTextureVertices, sizeof(aseTexCoord_t));
00423         } else if (!_pico_stricmp(p->token, "*mesh_numtvfaces")) {
00424             if (!_pico_parse_int(p, &numTextureVertexFaces))
00425                 _ase_error_return("Missing MESH_NUMTVFACES value");
00426         } else if (!_pico_stricmp(p->token, "*mesh_numcvertex")) {
00427             if (!_pico_parse_int(p, &numColorVertices))
00428                 _ase_error_return("Missing MESH_NUMCVERTEX value");
00429 
00430             colors = _pico_calloc(numColorVertices, sizeof(aseColor_t));
00431             memset(colors, 255, numColorVertices * sizeof(aseColor_t)); /* ydnar: force colors to white initially */
00432         } else if (!_pico_stricmp(p->token, "*mesh_numcvfaces")) {
00433             if (!_pico_parse_int(p, &numColorVertexFaces))
00434                 _ase_error_return("Missing MESH_NUMCVFACES value");
00435         }
00436         /* mesh material reference. this usually comes at the end of */
00437         /* geomobjects after the mesh blocks. we must assume that the */
00438         /* new mesh was already created so all we can do here is assign */
00439         /* the material reference id (shader index) now. */
00440         else if (!_pico_stricmp(p->token, "*material_ref")) {
00441             int mtlId;
00442 
00443             /* get the material ref (0..n) */
00444             if (!_pico_parse_int(p, &mtlId))
00445                 _ase_error_return("Missing material reference ID");
00446 
00447             {
00448                 int i = 0;
00449                 /* fix up all of the aseFaceList in the surface to point to the parent material */
00450                 /* we've already saved off their subMtl */
00451                 for (; i < numFaces; ++i) {
00452                     faces[i].materialId = mtlId;
00453                 }
00454             }
00455         }
00456         /* model mesh vertex */
00457         else if (!_pico_stricmp(p->token, "*mesh_vertex")) {
00458             int index;
00459 
00460             if (numVertices == 0)
00461                 _ase_error_return("Vertex parse error");
00462 
00463             /* get vertex data (orig: index +y -x +z) */
00464             if (!_pico_parse_int(p, &index))
00465                 _ase_error_return("Vertex parse error");
00466             if (!_pico_parse_vec(p, vertices[index].xyz))
00467                 _ase_error_return("Vertex parse error");
00468 
00469             vertices[index].id = vertexId++;
00470         }
00471         /* model mesh vertex normal */
00472         else if (!_pico_stricmp(p->token, "*mesh_vertexnormal")) {
00473             int index;
00474 
00475             if (numVertices == 0)
00476                 _ase_error_return("Vertex parse error");
00477 
00478             /* get vertex data (orig: index +y -x +z) */
00479             if (!_pico_parse_int(p, &index))
00480                 _ase_error_return("Vertex parse error");
00481             if (!_pico_parse_vec(p, vertices[index].normal))
00482                 _ase_error_return("Vertex parse error");
00483         }
00484         /* model mesh face */
00485         else if (!_pico_stricmp(p->token, "*mesh_face")) {
00486             picoIndex_t indexes[3];
00487             int index;
00488 
00489             if (numFaces == 0)
00490                 _ase_error_return("Face parse error");
00491 
00492             /* get face index */
00493             if (!_pico_parse_int(p, &index))
00494                 _ase_error_return("Face parse error");
00495 
00496             /* get 1st vertex index */
00497             _pico_parse(p, 0);
00498             if (!_pico_parse_int(p, &indexes[0]))
00499                 _ase_error_return("Face parse error");
00500 
00501             /* get 2nd vertex index */
00502             _pico_parse(p, 0);
00503             if (!_pico_parse_int(p, &indexes[1]))
00504                 _ase_error_return("Face parse error");
00505 
00506             /* get 3rd vertex index */
00507             _pico_parse(p, 0);
00508             if (!_pico_parse_int(p, &indexes[2]))
00509                 _ase_error_return("Face parse error");
00510 
00511             /* parse to the subMaterial ID */
00512             while (1) {
00513                 if (!_pico_parse(p, 0)) { /* EOL */
00514                     break;
00515                 }
00516                 if (!_pico_stricmp(p->token, "*MESH_SMOOTHING")) {
00517                     _pico_parse_int(p, &faces[index].smoothingGroup);
00518                 }
00519                 if (!_pico_stricmp(p->token, "*MESH_MTLID")) {
00520                     _pico_parse_int(p, &faces[index].subMaterialId);
00521                 }
00522             }
00523 
00524             faces[index].materialId = 0;
00525             faces[index].indices[0] = indexes[2];
00526             faces[index].indices[1] = indexes[1];
00527             faces[index].indices[2] = indexes[0];
00528         }
00529         /* model texture vertex */
00530         else if (!_pico_stricmp(p->token, "*mesh_tvert")) {
00531             int index;
00532 
00533             if (numVertices == 0)
00534                 _ase_error_return("Texture Vertex parse error");
00535 
00536             /* get uv vertex index */
00537             if (!_pico_parse_int(p, &index) || index >= numTextureVertices)
00538                 _ase_error_return("Texture vertex parse error");
00539 
00540             /* get uv vertex s */
00541             if (!_pico_parse_float(p, &texcoords[index].texcoord[0]))
00542                 _ase_error_return("Texture vertex parse error");
00543 
00544             /* get uv vertex t */
00545             if (!_pico_parse_float(p, &texcoords[index].texcoord[1]))
00546                 _ase_error_return("Texture vertex parse error");
00547 
00548             /* ydnar: invert t */
00549             texcoords[index].texcoord[1] = 1.0f - texcoords[index].texcoord[1];
00550         }
00551         /* ydnar: model mesh texture face */
00552         else if (!_pico_stricmp(p->token, "*mesh_tface")) {
00553             picoIndex_t indexes[3];
00554             int index;
00555 
00556             if (numFaces == 0)
00557                 _ase_error_return("Texture face parse error");
00558 
00559             /* get face index */
00560             if (!_pico_parse_int(p, &index))
00561                 _ase_error_return("Texture face parse error");
00562 
00563             /* get 1st vertex index */
00564             if (!_pico_parse_int(p, &indexes[0]))
00565                 _ase_error_return("Texture face parse error");
00566 
00567             /* get 2nd vertex index */
00568             if (!_pico_parse_int(p, &indexes[1]))
00569                 _ase_error_return("Texture face parse error");
00570 
00571             /* get 3rd vertex index */
00572             if (!_pico_parse_int(p, &indexes[2]))
00573                 _ase_error_return("Texture face parse error");
00574 
00575             faces[index].indices[3] = indexes[2];
00576             faces[index].indices[4] = indexes[1];
00577             faces[index].indices[5] = indexes[0];
00578         }
00579         /* model color vertex */
00580         else if (!_pico_stricmp(p->token, "*mesh_vertcol")) {
00581             int index;
00582             float colorInput;
00583 
00584             if (numVertices == 0)
00585                 _ase_error_return("Color Vertex parse error");
00586 
00587             /* get color vertex index */
00588             if (!_pico_parse_int(p, &index))
00589                 _ase_error_return("Color vertex parse error");
00590 
00591             /* get R component */
00592             if (!_pico_parse_float(p, &colorInput))
00593                 _ase_error_return("Color vertex parse error");
00594             colors[index].color[0] = (picoByte_t) (colorInput * 255);
00595 
00596             /* get G component */
00597             if (!_pico_parse_float(p, &colorInput))
00598                 _ase_error_return("Color vertex parse error");
00599             colors[index].color[1] = (picoByte_t) (colorInput * 255);
00600 
00601             /* get B component */
00602             if (!_pico_parse_float(p, &colorInput))
00603                 _ase_error_return("Color vertex parse error");
00604             colors[index].color[2] = (picoByte_t) (colorInput * 255);
00605 
00606             /* leave alpha alone since we don't get any data from the ASE format */
00607             colors[index].color[3] = 255;
00608         }
00609         /* model color face */
00610         else if (!_pico_stricmp(p->token, "*mesh_cface")) {
00611             picoIndex_t indexes[3];
00612             int index;
00613 
00614             if (numFaces == 0)
00615                 _ase_error_return("Face parse error");
00616 
00617             /* get face index */
00618             if (!_pico_parse_int(p, &index))
00619                 _ase_error_return("Face parse error");
00620 
00621             /* get 1st cvertex index */
00622             if (!_pico_parse_int(p, &indexes[0]))
00623                 _ase_error_return("Face parse error");
00624 
00625             /* get 2nd cvertex index */
00626             if (!_pico_parse_int(p, &indexes[1]))
00627                 _ase_error_return("Face parse error");
00628 
00629             /* get 3rd cvertex index */
00630             if (!_pico_parse_int(p, &indexes[2]))
00631                 _ase_error_return("Face parse error");
00632 
00633             faces[index].indices[6] = indexes[2];
00634             faces[index].indices[7] = indexes[1];
00635             faces[index].indices[8] = indexes[0];
00636         }
00637         /* model material */
00638         else if (!_pico_stricmp(p->token, "*material")) {
00639             aseSubMaterial_t*subMaterial = NULL;
00640             picoShader_t *shader = NULL;
00641             int level = 1, index;
00642             char materialName[1024];
00643             float transValue = 0.0f, shineValue = 1.0f;
00644             picoColor_t ambientColor, diffuseColor, specularColor;
00645             char *mapname = NULL;
00646             int subMtlId, subMaterialLevel = -1;
00647 
00648             /* get material index */
00649             _pico_parse_int(p, &index);
00650 
00651             /* check brace */
00652             if (!_pico_parse_check(p, 1, "{"))
00653                 _ase_error_return("Material missing opening brace");
00654 
00655             /* parse material block */
00656             while (1) {
00657                 /* get next token */
00658                 if (_pico_parse(p, 1) == NULL)
00659                     break;
00660                 if (!strlen(p->token))
00661                     continue;
00662 
00663                 /* handle levels */
00664                 if (p->token[0] == '{')
00665                     level++;
00666                 else if (p->token[0] == '}')
00667                     level--;
00668                 if (!level)
00669                     break;
00670 
00671                 if (level == subMaterialLevel) {
00672                     /* set material name */
00673                     _pico_first_token(materialName);
00674                     shadername_convert(materialName);
00675                     PicoSetShaderName(shader, materialName);
00676 
00677                     /* set shader's transparency */
00678                     PicoSetShaderTransparency(shader, transValue);
00679 
00680                     /* set shader's ambient color */
00681                     PicoSetShaderAmbientColor(shader, ambientColor);
00682 
00683                     /* set diffuse alpha to transparency */
00684                     diffuseColor[3] = (picoByte_t) (transValue * 255.0);
00685 
00686                     /* set shader's diffuse color */
00687                     PicoSetShaderDiffuseColor(shader, diffuseColor);
00688 
00689                     /* set shader's specular color */
00690                     PicoSetShaderSpecularColor(shader, specularColor);
00691 
00692                     /* set shader's shininess */
00693                     PicoSetShaderShininess(shader, shineValue);
00694 
00695                     /* set material map name */
00696                     PicoSetShaderMapName(shader, mapname);
00697 
00698                     subMaterial = _ase_add_submaterial(&materials, index, subMtlId, shader);
00699                     subMaterialLevel = -1;
00700                 }
00701 
00702                 /* parse submaterial index */
00703                 if (!_pico_stricmp(p->token, "*submaterial")) {
00704                     /* allocate new pico shader */
00705                     _pico_parse_int(p, &subMtlId);
00706 
00707                     shader = PicoNewShader(model);
00708                     if (shader == NULL) {
00709                         PicoFreeModel(model);
00710                         return NULL;
00711                     }
00712                     subMaterialLevel = level;
00713                 }
00714                 /* parse material name */
00715                 else if (!_pico_stricmp(p->token, "*material_name")) {
00716                     char* name = _pico_parse(p, 0);
00717                     if (name == NULL)
00718                         _ase_error_return("Missing material name");
00719 
00720                     strcpy(materialName, name);
00721                     /* skip rest and continue with next token */
00722                     _pico_parse_skip_rest(p);
00723                     continue;
00724                 }
00725                 /* parse material transparency */
00726                 else if (!_pico_stricmp(p->token, "*material_transparency")) {
00727                     /* get transparency value from ase */
00728                     if (!_pico_parse_float(p, &transValue))
00729                         _ase_error_return("Material transparency parse error");
00730 
00731                     /* skip rest and continue with next token */
00732                     _pico_parse_skip_rest(p);
00733                     continue;
00734                 }
00735                 /* parse material shininess */
00736                 else if (!_pico_stricmp(p->token, "*material_shine")) {
00737                     /* remark:
00738                      * - not sure but instead of '*material_shine' i might
00739                      *   need to use '*material_shinestrength' */
00740 
00741                     /* get shine value from ase */
00742                     if (!_pico_parse_float(p, &shineValue))
00743                         _ase_error_return("Material shine parse error");
00744 
00745                     /* scale ase shine range 0..1 to pico range 0..127 */
00746                     shineValue *= 128.0;
00747 
00748                     /* skip rest and continue with next token */
00749                     _pico_parse_skip_rest(p);
00750                     continue;
00751                 }
00752                 /* parse ambient material color */
00753                 else if (!_pico_stricmp(p->token, "*material_ambient")) {
00754                     picoVec3_t vec;
00755                     /* get r,g,b float values from ase */
00756                     if (!_pico_parse_vec(p, vec))
00757                         _ase_error_return("Material color parse error");
00758 
00759                     /* setup 0..255 range color values */
00760                     ambientColor[0] = (int) (vec[0] * 255.0);
00761                     ambientColor[1] = (int) (vec[1] * 255.0);
00762                     ambientColor[2] = (int) (vec[2] * 255.0);
00763                     ambientColor[3] = (int) (255);
00764 
00765                     /* skip rest and continue with next token */
00766                     _pico_parse_skip_rest(p);
00767                     continue;
00768                 }
00769                 /* parse diffuse material color */
00770                 else if (!_pico_stricmp(p->token, "*material_diffuse")) {
00771                     picoVec3_t vec;
00772 
00773                     /* get r,g,b float values from ase */
00774                     if (!_pico_parse_vec(p, vec))
00775                         _ase_error_return("Material color parse error");
00776 
00777                     /* setup 0..255 range color */
00778                     diffuseColor[0] = (int) (vec[0] * 255.0);
00779                     diffuseColor[1] = (int) (vec[1] * 255.0);
00780                     diffuseColor[2] = (int) (vec[2] * 255.0);
00781                     diffuseColor[3] = (int) (255);
00782 
00783                     /* skip rest and continue with next token */
00784                     _pico_parse_skip_rest(p);
00785                     continue;
00786                 }
00787                 /* parse specular material color */
00788                 else if (!_pico_stricmp(p->token, "*material_specular")) {
00789                     picoVec3_t vec;
00790 
00791                     /* get r,g,b float values from ase */
00792                     if (!_pico_parse_vec(p, vec))
00793                         _ase_error_return("Material color parse error");
00794 
00795                     /* setup 0..255 range color */
00796                     specularColor[0] = (int) (vec[0] * 255);
00797                     specularColor[1] = (int) (vec[1] * 255);
00798                     specularColor[2] = (int) (vec[2] * 255);
00799                     specularColor[3] = (int) (255);
00800 
00801                     /* skip rest and continue with next token */
00802                     _pico_parse_skip_rest(p);
00803                     continue;
00804                 }
00805                 /* material diffuse map */
00806                 else if (!_pico_stricmp(p->token, "*map_diffuse")) {
00807                     int sublevel = 0;
00808 
00809                     /* parse material block */
00810                     while (1) {
00811                         /* get next token */
00812                         if (_pico_parse(p, 1) == NULL)
00813                             break;
00814                         if (!strlen(p->token))
00815                             continue;
00816 
00817                         /* handle levels */
00818                         if (p->token[0] == '{')
00819                             sublevel++;
00820                         else if (p->token[0] == '}')
00821                             sublevel--;
00822                         if (!sublevel)
00823                             break;
00824 
00825                         /* parse diffuse map bitmap */
00826                         if (!_pico_stricmp(p->token, "*bitmap")) {
00827                             char* name = _pico_parse(p, 0);
00828                             if (name == NULL)
00829                                 _ase_error_return("Missing material map bitmap name");
00830                             mapname = _pico_alloc(strlen(name) + 1);
00831                             strcpy(mapname, name);
00832                             /* skip rest and continue with next token */
00833                             _pico_parse_skip_rest(p);
00834                             continue;
00835                         }
00836                     }
00837                 }
00838                 /* end map_diffuse block */
00839             }
00840             /* end material block */
00841 
00842             if (subMaterial == NULL) {
00843                 /* allocate new pico shader */
00844                 shader = PicoNewShader(model);
00845                 if (shader == NULL) {
00846                     PicoFreeModel(model);
00847                     return NULL;
00848                 }
00849 
00850                 /* set material name */
00851                 shadername_convert(materialName);
00852                 PicoSetShaderName(shader, materialName);
00853 
00854                 /* set shader's transparency */
00855                 PicoSetShaderTransparency(shader, transValue);
00856 
00857                 /* set shader's ambient color */
00858                 PicoSetShaderAmbientColor(shader, ambientColor);
00859 
00860                 /* set diffuse alpha to transparency */
00861                 diffuseColor[3] = (picoByte_t) (transValue * 255.0);
00862 
00863                 /* set shader's diffuse color */
00864                 PicoSetShaderDiffuseColor(shader, diffuseColor);
00865 
00866                 /* set shader's specular color */
00867                 PicoSetShaderSpecularColor(shader, specularColor);
00868 
00869                 /* set shader's shininess */
00870                 PicoSetShaderShininess(shader, shineValue);
00871 
00872                 /* set material map name */
00873                 PicoSetShaderMapName(shader, mapname);
00874 
00875                 /* extract shadername from bitmap path */
00876                 if (mapname != NULL) {
00877                     char* p = mapname;
00878 
00879                     /* convert to shader-name format */
00880                     shadername_convert(mapname);
00881                     {
00882                         /* remove extension */
00883                         char* last_period = strrchr(p, '.');
00884                         if (last_period != NULL) {
00885                             *last_period = '\0';
00886                         }
00887                     }
00888 
00889                     /* find shader path */
00890                     for (; *p != '\0'; ++p) {
00891                         if (_pico_strnicmp(p, "models/", 7) == 0 || _pico_strnicmp(p, "textures/", 9) == 0) {
00892                             break;
00893                         }
00894                     }
00895 
00896                     if (*p != '\0') {
00897                         /* set material name */
00898                         PicoSetShaderName(shader, p);
00899                     }
00900                 }
00901 
00902                 /* this is just a material with 1 submaterial */
00903                 subMaterial = _ase_add_submaterial(&materials, index, 0, shader);
00904             }
00905 
00906             /* ydnar: free mapname */
00907             if (mapname != NULL)
00908                 _pico_free(mapname);
00909         }
00910 
00911         /* skip unparsed rest of line and continue */
00912         _pico_parse_skip_rest(p);
00913     }
00914 
00915     /* ydnar: finish existing surface */
00916     _ase_submit_triangles(model, materials, vertices, texcoords, colors, faces, numFaces);
00917     _pico_free(faces);
00918     _pico_free(vertices);
00919     _pico_free(texcoords);
00920     _pico_free(colors);
00921 
00922 #ifdef DEBUG_PM_ASE
00923     _ase_print_materials(materials);
00924     finish = clock();
00925     elapsed = (double)(finish - start) / CLOCKS_PER_SEC;
00926     _pico_printf(PICO_NORMAL, "Loaded model in in %-.2f second(s)\n", elapsed);
00927 #endif
00928 
00929     _ase_free_materials(&materials);
00930 
00931     _pico_free_parser(p);
00932 
00933     /* return allocated pico model */
00934     return model;
00935 }
00936 
00937 /* pico file format module definition */
00938 const picoModule_t picoModuleASE = { "1.0", /* module version string */
00939 "Autodesk 3DSMAX ASCII", /* module display name */
00940 "Jared Hefty, seaw0lf", /* author's name */
00941 "2003 Jared Hefty, 2002 seaw0lf", /* module copyright */
00942 { "ase", NULL, NULL, NULL /* default extensions to use */
00943 }, _ase_canload, /* validation routine */
00944 _ase_load, /* load routine */
00945 NULL, /* save validation routine */
00946 NULL /* save routine */
00947 };

Generated by  doxygen 1.6.2