
/*
    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 <psconfig.h>
#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
}

/******************************************************************************/
