/* Crystal Space 3d format converter Based on IVCON - converts various 3D graphics file Author: John Burkardt - used with permission CS adaption and conversion to C++ classes Bruce Williams This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include "ase2spr.h" int converter::ase_convert(FILE * filein, char *fileout_name) { float bval; int count; float gval; int i; int iface = 0; int ivert = 0; int itvert = 0; int itface = 0; int iword; int j; int level; int nbase; char *next; int nlbrack; int nrbrack; float rval; float temp; int width; char word[MAX_INCHARS]; char word1[MAX_INCHARS]; char word2[MAX_INCHARS]; char wordm1[MAX_INCHARS]; char* objectname = strdup("obj"); float x; float y; float z; float u; float v; float w; int frameNumber = 0; FILE *fileout = NULL; level = 0; strcpy(levnam[0], "Top"); nbase = 0; nlbrack = 0; nrbrack = 0; strcpy(word, " "); strcpy(wordm1, " "); /* Read a line of text from the file. */ while (true) { if (fgets(input, MAX_INCHARS, filein) == NULL) { break; } num_text = num_text + 1; next = input; iword = 0; /* Read the next word from the line. */ while (true) { strcpy(wordm1, word); strcpy(word, " "); count = sscanf(next, "%s%n", word, &width); next = next + width; if (count <= 0) { break; } iword = iword + 1; if (iword == 1) { strcpy(word1, word); } /* In case the converternew word is a bracket, update the bracket count. */ if (strcmp(word, "{") == 0) { nlbrack++; level = nlbrack - nrbrack; strcpy(levnam[level], wordm1); } else if (strcmp(word, "}") == 0) { nrbrack = nrbrack + 1; if (nlbrack < nrbrack) { fprintf(logfile, "\n"); fprintf(logfile, "ASE_READ - Fatal error!\n"); fprintf(logfile, " Extraneous right bracket on line %d\n", num_text); fprintf(logfile, "Currently processing field:\n"); fprintf(logfile, "%s\n", levnam[level]); return -1; } } /* *3DSMAX_ASCIIEXPORT 200 */ if (strcmp(word1, "*3DSMAX_ASCIIEXPORT") == 0) { break; } /* *COMMENT */ else if (strcmp(word1, "*COMMENT") == 0) { break; } /* *GEOMOBJECT */ else if (strcmp(levnam[level], "*GEOMOBJECT") == 0) { if (strcmp(word, "{") == 0) { continue; } else if (strcmp(word, "}") == 0) { level = nlbrack - nrbrack; // if we have found no animation // we should save the file here with ONE FRAME only if (fileout == NULL) { fprintf (logfile, "***Warning: No animation found!" "Saving 1 static frame!\n"); fileout = fopen(fileout_name, "w"); spr_write_header(fileout, objectname); spr_write_frame(fileout, 1); spr_write_footer(fileout, 1); fclose(fileout); fileout = NULL; } continue; } /* Why don't you read and save this name? */ else if (strcmp(word, "*NODE_NAME") == 0) { // extract text between "" char *name, *pos1, *pos2; pos1=strchr(next,'\"'); if (!pos1) break; pos1++; pos2 = strchr(pos1, '\"'); if (!pos2) break; name = (char*) malloc(pos2-pos1+1); name = strncpy(name, pos1, pos2-pos1); if (objectname) free(objectname); objectname = name; break; } else if (strcmp(word, "*NODE_TM") == 0) { continue; } else if (strcmp(word, "*MESH") == 0) { continue; } else if (strcmp(word, "*PROP_CASTSHADOW") == 0) { break; } else if (strcmp(word, "*PROP_MOTIONBLUR") == 0) { break; } else if (strcmp(word, "*PROP_RECVSHADOW") == 0) { break; } else if (strcmp(word, "*MATERIAL_REF") == 0) { break; } else if (strcmp(word, "*MESH_ANIMATION") == 0) { continue; } else { num_bad = num_bad + 1; fprintf(logfile, "Bad data in GEOMOBJECT, line %d\n", num_text); break; } } /* *MESH */ else if (strcmp(levnam[level], "*MESH") == 0) { if (strcmp(word, "{") == 0) { continue; } else if (strcmp(word, "}") == 0) { level = nlbrack - nrbrack; continue; } else if (strcmp(word, "*MESH_CFACELIST") == 0) { continue; } else if (strcmp(word, "*MESH_CVERTLIST") == 0) { continue; } else if (strcmp(word, "*MESH_FACE_LIST") == 0) { continue; } else if (strcmp(word, "*MESH_NORMALS") == 0) { continue; } else if (strcmp(word, "*MESH_NUMCVERTEX") == 0) { break; } else if (strcmp(word, "*MESH_NUMCVFACES") == 0) { break; } else if (strcmp(word, "*MESH_NUMFACES") == 0) { break; } else if (strcmp(word, "*MESH_NUMTVERTEX") == 0) { break; } else if (strcmp(word, "*MESH_NUMTVFACES") == 0) { break; } else if (strcmp(word, "*MESH_NUMVERTEX") == 0) { break; } else if (strcmp(word, "*MESH_TFACELIST") == 0) { continue; } else if (strcmp(word, "*MESH_TVERTLIST") == 0) { continue; } else if (strcmp(word, "*MESH_VERTEX_LIST") == 0) { continue; } // this field tells which frame we are looking at else if (strcmp(word, "*TIMEVALUE") == 0) { // Looks if we are in MESH_ANIMATION if (strcmp(levnam[level - 1], "*MESH_ANIMATION") == 0) { // have we already read one frame? if (num_cor3 != 0) { frameNumber++; // we must output one frame if (fileout == NULL) { fileout = fopen(fileout_name, "w"); spr_write_header(fileout, objectname); } spr_write_frame(fileout, frameNumber); // we must clear the data structures data_init(); } // we continue until next frame break; } break; } else { num_bad = num_bad + 1; fprintf(logfile, "Bad data in MESH, line %d\n", num_text); break; } } /* *MESH_CFACELIST */ else if (strcmp(levnam[level], "*MESH_CFACELIST") == 0) { if (strcmp(word, "{") == 0) { continue; } else if (strcmp(word, "}") == 0) { level = nlbrack - nrbrack; continue; } else if (strcmp(word, "*MESH_CFACE") == 0) { break; } else { num_bad = num_bad + 1; fprintf(logfile, "Bad data in MESH_CFACE, line %d\n", num_text); break; } } /* *MESH_CVERTLIST Mesh vertex indices must be incremented by NBASE+1 before being stored in the internal array. */ else if (strcmp(levnam[level], "*MESH_CVERTLIST") == 0) { if (strcmp(word, "{") == 0) { continue; } else if (strcmp(word, "}") == 0) { level = nlbrack - nrbrack; continue; } else if (strcmp(word, "*MESH_VERTCOL") == 0) { count = sscanf(next, "%d%n", &i, &width); next = next + width; i = i + nbase; count = sscanf(next, "%f%n", &rval, &width); next = next + width; count = sscanf(next, "%f%n", &gval, &width); next = next + width; count = sscanf(next, "%f%n", &bval, &width); next = next + width; if (i < MAX_COR3) { cor3_rgb[0][i] = rval; cor3_rgb[1][i] = gval; cor3_rgb[2][i] = bval; } } else { num_bad = num_bad + 1; fprintf(logfile, "Bad data in MESH_CVERTLIST, line %d\n", num_text); break; } } /* *MESH_FACE_LIST This coding assumes a face is always triangular or quadrilateral. */ else if (strcmp(levnam[level], "*MESH_FACE_LIST") == 0) { if (strcmp(word, "{") == 0) { continue; } else if (strcmp(word, "}") == 0) { level = nlbrack - nrbrack; continue; } else if (strcmp(word, "*MESH_FACE") == 0) { if (num_face < MAX_FACE) { count = sscanf(next, "%d%n", &i, &width); next = next + width; count = sscanf(next, "%s%n", word2, &width); next = next + width; count = sscanf(next, "%s%n", word2, &width); next = next + width; // A: x count = sscanf(next, "%d%n", &i, &width); next = next + width; face[0][num_face] = i + nbase; face_mat[0][num_face] = 0; face_order[num_face] = face_order[num_face] + 1; count = sscanf(next, "%s%n", word2, &width); next = next + width; // B: x count = sscanf(next, "%d%n", &i, &width); next = next + width; face[1][num_face] = i + nbase; face_mat[1][num_face] = 0; face_order[num_face] = face_order[num_face] + 1; count = sscanf(next, "%s%n", word2, &width); next = next + width; // C: x count = sscanf(next, "%d%n", &i, &width); next = next + width; face[2][num_face] = i + nbase; face_mat[2][num_face] = 0; face_order[num_face] = face_order[num_face] + 1; count = sscanf(next, "%s%n", word2, &width); next = next + width; if (strcmp(word2, "D:") == 0) { count = sscanf(next, "%d%n", &i, &width); next = next + width; face[3][num_face] = i + nbase; face_mat[3][num_face] = 0; face_order[num_face] = face_order[num_face] + 1; } } num_face = num_face + 1; break; } else { num_bad = num_bad + 1; fprintf(logfile, "Bad data in MESH_FACE_LIST, line %d\n", num_text); break; } } /* *SCENE_ENVMAP */ else if (strcmp(levnam[level], "*SCENE_ENVMAP") == 0) { if (strcmp(word, "{") == 0) { continue; } else if (strcmp(word, "}") == 0) { level = nlbrack - nrbrack; continue; } else if (strcmp(word, "*MAP_NAME") == 0) { break; } else if (strcmp(word, "*MAP_CLASS") == 0) { break; } else if (strcmp(word, "*MAP_SUBNO") == 0) { break; } else if (strcmp(word, "*MAP_AMOUNT") == 0) { break; } else if (strcmp(word, "*BITMAP") == 0) { break; } else if (strcmp(word, "*MAP_TYPE") == 0) { break; } else if (strcmp(word, "*UVW_U_OFFSET") == 0) { break; } else if (strcmp(word, "*UVW_V_OFFSET") == 0) { break; } else if (strcmp(word, "*UVW_U_TILING") == 0) { break; } else if (strcmp(word, "*UVW_V_TILING") == 0) { break; } else if (strcmp(word, "*UVW_ANGLE") == 0) { break; } else if (strcmp(word, "*UVW_BLUR") == 0) { break; } else if (strcmp(word, "*UVW_BLUR_OFFSET") == 0) { break; } else if (strcmp(word, "*UVW_NOUSE_AMT") == 0) { break; } else if (strcmp(word, "*UVW_NOISE_SIZE") == 0) { break; } else if (strcmp(word, "*UVW_NOISE_LEVEL") == 0) { break; } else if (strcmp(word, "*UVW_NOISE_PHASE") == 0) { break; } else if (strcmp(word, "*BITMAP_FILTER") == 0) { break; } } /* *MESH_TVERTLIST */ else if (strcmp(levnam[level], "*MESH_TVERTLIST") == 0) { if (strcmp(word, "{") == 0) { continue; } else if (strcmp(word, "}") == 0) { level = nlbrack - nrbrack; continue; } else if (strcmp(word, "*MESH_TVERT") == 0) { count = sscanf(next, "%d%n", &itvert, &width); next = next + width; count = sscanf(next, "%f%n", &u, &width); next = next + width; count = sscanf(next, "%f%n", &v, &width); next = next + width; // this value is always 0.0 - ignored count = sscanf(next, "%f%n", &w, &width); next = next + width; itvert = itvert + nbase; ivert = 0; vertex_uv[0][0][itvert] = u; vertex_uv[1][0][itvert] = v; //vertex_uv[2][0][itvert] = w; - ignored break; } else { num_bad = num_bad + 1; fprintf(logfile, "Bad data in MESH_TVERTLIST, line %d\n", num_text); break; } } /* *MESH_NORMALS */ else if (strcmp(levnam[level], "*MESH_NORMALS") == 0) { if (strcmp(word, "{") == 0) { continue; } else if (strcmp(word, "}") == 0) { level = nlbrack - nrbrack; continue; } else if (strcmp(word, "*MESH_FACENORMAL") == 0) { count = sscanf(next, "%d%n", &iface, &width); next = next + width; count = sscanf(next, "%f%n", &x, &width); next = next + width; count = sscanf(next, "%f%n", &y, &width); next = next + width; count = sscanf(next, "%f%n", &z, &width); next = next + width; iface = iface + nbase; ivert = 0; face_normal[0][iface] = x; face_normal[1][iface] = y; face_normal[2][iface] = z; break; } else if (strcmp(word, "*MESH_VERTEXNORMAL") == 0) { count = sscanf(next, "%d%n", &i, &width); next = next + width; count = sscanf(next, "%f%n", &x, &width); next = next + width; count = sscanf(next, "%f%n", &y, &width); next = next + width; count = sscanf(next, "%f%n", &z, &width); next = next + width; vertex_normal[0][ivert][iface] = x; vertex_normal[1][ivert][iface] = y; vertex_normal[2][ivert][iface] = z; ivert = ivert + 1; break; } else { num_bad = num_bad + 1; fprintf(logfile, "Bad data in MESH_NORMALS, line %d\n", num_text); break; } } /* *MESH_TFACELIST */ else if (strcmp(levnam[level], "*MESH_TFACELIST") == 0) { if (strcmp(word, "{") == 0) { continue; } else if (strcmp(word, "}") == 0) { level = nlbrack - nrbrack; continue; } else if (strcmp(word, "*MESH_TFACE") == 0) { count = sscanf(next, "%d%n", &itface, &width); next = next + width; count = sscanf(next, "%f%n", &x, &width); next = next + width; count = sscanf(next, "%f%n", &y, &width); next = next + width; count = sscanf(next, "%f%n", &z, &width); next = next + width; itface = itface + nbase; ivert = 0; // vertex 1 face_uv[0][0][itface] = x; // vertex 2 face_uv[1][0][itface] = y; // vertex 3 face_uv[2][0][itface] = z; break; } else { num_bad = num_bad + 1; fprintf(logfile, "Bad data in MESH_TFACE_LIST, line %d\n", num_text); break; } } /* *MESH_VERTEX_LIST */ else if (strcmp(levnam[level], "*MESH_VERTEX_LIST") == 0) { if (strcmp(word, "{") == 0) { nbase = num_cor3; continue; } else if (strcmp(word, "}") == 0) { level = nlbrack - nrbrack; continue; } else if (strcmp(word1, "*MESH_VERTEX") == 0) { count = sscanf(next, "%d%n", &i, &width); next = next + width; count = sscanf(next, "%f%n", &x, &width); next = next + width; count = sscanf(next, "%f%n", &y, &width); next = next + width; count = sscanf(next, "%f%n", &z, &width); next = next + width; i = i + nbase; num_cor3 = MAX(num_cor3, i + 1); if (i < MAX_COR3) { cor3[0][i] = x; cor3[1][i] = y; cor3[2][i] = z; /* cor3[0][i] = transform_mat[0][0] * x + transform_mat[0][1] * y + transform_mat[0][2] * z + transform_mat[0][3]; cor3[1][i] = transform_mat[1][0] * x + transform_mat[1][1] * y + transform_mat[1][2] * z + transform_mat[1][3]; cor3[2][i] = transform_mat[2][0] * x + transform_mat[2][1] * y + transform_mat[2][2] * z + transform_mat[2][3]; */ } break; } else { num_bad = num_bad + 1; fprintf(logfile, "Bad data in MESH_VERTEX_LIST, line %d\n", num_text); break; } } /* *NODE_TM Each node should start out with a default transformation matrix. */ else if (strcmp(levnam[level], "*NODE_TM") == 0) { if (strcmp(word, "{") == 0) { for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { if (i == j) { transform_mat[j][i] = 1.0; } else { transform_mat[j][i] = 0.0; } } } continue; } else if (strcmp(word, "}") == 0) { level = nlbrack - nrbrack; continue; } else if (strcmp(word, "*INHERIT_POS") == 0) { break; } else if (strcmp(word, "*INHERIT_ROT") == 0) { break; } else if (strcmp(word, "*INHERIT_SCL") == 0) { break; } else if (strcmp(word, "*NODE_NAME") == 0) { break; } else if (strcmp(word, "*TM_POS") == 0) { break; } else if (strcmp(word, "*TM_ROTANGLE") == 0) { break; } else if (strcmp(word, "*TM_ROTAXIS") == 0) { break; } else if (strcmp(word, "*TM_ROW0") == 0) { count = sscanf(next, "%f%n", &temp, &width); next = next + width; transform_mat[0][0] = temp; count = sscanf(next, "%f%n", &temp, &width); next = next + width; transform_mat[1][0] = temp; count = sscanf(next, "%f%n", &temp, &width); next = next + width; transform_mat[2][0] = temp; break; } else if (strcmp(word, "*TM_ROW1") == 0) { count = sscanf(next, "%f%n", &temp, &width); next = next + width; transform_mat[0][1] = temp; count = sscanf(next, "%f%n", &temp, &width); next = next + width; transform_mat[1][1] = temp; count = sscanf(next, "%f%n", &temp, &width); next = next + width; transform_mat[2][1] = temp; break; } else if (strcmp(word, "*TM_ROW2") == 0) { count = sscanf(next, "%f%n", &temp, &width); next = next + width; transform_mat[0][2] = temp; count = sscanf(next, "%f%n", &temp, &width); next = next + width; transform_mat[1][2] = temp; count = sscanf(next, "%f%n", &temp, &width); next = next + width; transform_mat[2][2] = temp; break; } else if (strcmp(word, "*TM_ROW3") == 0) { count = sscanf(next, "%f%n", &temp, &width); next = next + width; transform_mat[0][3] = temp; count = sscanf(next, "%f%n", &temp, &width); next = next + width; transform_mat[1][3] = temp; count = sscanf(next, "%f%n", &temp, &width); next = next + width; transform_mat[2][3] = temp; break; } else if (strcmp(word, "*TM_SCALE") == 0) { break; } else if (strcmp(word, "*TM_SCALEAXIS") == 0) { break; } else if (strcmp(word, "*TM_SCALEAXISANG") == 0) { break; } else { num_bad = num_bad + 1; fprintf(logfile, "Bad data in NODE_TM, line %d\n", num_text); break; } } /* *SCENE */ else if (strcmp(levnam[level], "*SCENE") == 0) { if (strcmp(word, "{") == 0) { continue; } else if (strcmp(word, "}") == 0) { level = nlbrack - nrbrack; continue; } else if (strcmp(word, "*SCENE_AMBIENT_STATIC") == 0) { break; } else if (strcmp(word, "*SCENE_BACKGROUND_STATIC") == 0) { break; } else if (strcmp(word, "*SCENE_FILENAME") == 0) { break; } else if (strcmp(word, "*SCENE_FIRSTFRAME") == 0) { break; } else if (strcmp(word, "*SCENE_FRAMESPEED") == 0) { break; } else if (strcmp(word, "*SCENE_LASTFRAME") == 0) { break; } else if (strcmp(word, "*SCENE_TICKSPERFRAME") == 0) { break; } else if (strcmp(word, "*SCENE_ENVMAP") == 0) { continue; } else { num_bad = num_bad + 1; fprintf(logfile, "Bad data in SCENE, line %d\n", num_text); break; } } /* *MESH_ANIMATION */ else if (strcmp(levnam[level], "*MESH_ANIMATION") == 0) { if (strcmp(word, "{") == 0) { // we can output the static frame read until now // TODO if needed // we must clear the data structures to remove static frame and prepare for first animated frame data_init(); continue; } else if (strcmp(word, "}") == 0) { // we must close the spr file. if (fileout != NULL) { spr_write_footer(fileout, frameNumber); } level = nlbrack - nrbrack; continue; } else if (strcmp(word, "*MESH") == 0) { continue; } else { num_bad = num_bad + 1; fprintf(logfile, "Bad data in MESH_ANIMATION, line %d\n", num_text); break; } } } /* End of loop reading words from the line. */ } /* End of loop reading lines from input file. */ if ( fileout ) fclose(fileout); return 0; // XXX: What the hell is this good for? It's never used #if 0 /* Assign face vertex colors based on node colors. */ khi = MIN(num_face, MAX_FACE); for (iface = 0; iface < khi; iface++) { for (ivert = 0; ivert < 3; ivert++) { l = face[ivert][iface]; for (i = 0; i < 3; i++) { vertex_rgb[i][ivert][iface] = cor3_rgb[i][l]; } } } #endif } /******************************************************************************/