VRML 2.0 (.wrl) custom parser code

Moderator
Posts: 373
Joined: 2006.08
Post: #1
Well, I just got done finishing the first draft of a program that parses a .wrl (Virtual Reality Modeling Language 2.0) file, and I thought I would post the code in case anyones interested.
The code should be relatively easy to modify to fit your own custom format, and if anyone is interested in it, I'll comment it and post another copy Smile

Anyway, here goes:
object.hpp:
Code:
#ifndef OBJECT_HPP
#define OBJECT_HPP

#include <stdio.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <sstream>

#define SRB '{'
#define SLB '}'

#define DRB "{"
#define DLB "}"

using namespace std;

class object
{
      public:
      int numOfObjects;
      int tier;
      int id;
      bool locked;
      
      double transX;
      double transY;
      double transZ;
      
      double angle;
      double rotX;
      double rotY;
      double rotZ;
      
      int numOfIndexedShapes;
      int currentShapeIndex;
      vector<string> coords;
      vector<int> indexedCoords;
      vector<int> indexedInShape;
      vector<string> textureCoords;
      vector<int> indexedTextureCoords;
      
      string name;
      vector<object> objects;

      object();
      ~object();
      
      void makeNew();
      void lockLast();
      void setLastName(char theName[]);
      void setLastTier(int theTier);
      void setLastRotation(double theAngle, double theX, double theY, double theZ);
      void setLastTranslation(double theX, double theY, double theZ);
      void setLastId(int theId);
      void addLastCoord(char theCoord[]);
      void addLastTextureCoord(char theCoord[]);
      void endIndexShape();
      void addLastIndexCoord(int theCoord);
      void addLastIndexTextureCoord(int theCoord);
      int getTotal();
      string output();
};

#endif

object.cpp:
Code:
#include "object.hpp"

object::object()
{
    numOfObjects = -1;
    name = "";
    locked = 0;

    transX = 0.0;
    transY = 0.0;
    transZ = 0.0;

    angle = 0.0;
    rotX = 0.0;
    rotY = 0.0;
    rotZ = 0.0;

    numOfIndexedShapes = -1;
    currentShapeIndex = -1;
}

object::~object()
{ }
void object::makeNew()
{
    int lastFound = -1;
    /*~~~~~~~~~~~~~~~*/

    for(int i = 0; i <= numOfObjects; i++)
    {
        if(!objects[i].locked)
        {
            lastFound = i;
            i = numOfObjects + 1;
        }
    }

    if(lastFound == -1)
    {
        object  tempObject;
        objects.push_back(tempObject);
        numOfObjects = numOfObjects + 1;
    }
    else
    {
        objects[lastFound].makeNew();
    }
}

void object::lockLast()
{
    int lastFound = -1;
    for(int i = 0; i <= numOfObjects; i++)
    {
        if(!objects[i].locked)
        {
            lastFound = i;
            i = numOfObjects + 1;
        }
    }

    if(lastFound == -1)
    {
        locked = 1;
    }
    else
    {
        objects[lastFound].lockLast();
    }
}

void object::setLastName(char theName[])
{
    int lastFound = -1;
    for(int i = 0; i <= numOfObjects; i++)
    {
        if(!objects[i].locked)
        {
            lastFound = i;
            i = numOfObjects + 1;
        }
    }

    if(lastFound == -1)
    {
        name = theName;
    }
    else
    {
        objects[lastFound].setLastName(theName);
    }
}

void object::setLastTier(int theTier)
{
    int lastFound = -1;
    for(int i = 0; i <= numOfObjects; i++)
    {
        if(!objects[i].locked)
        {
            lastFound = i;
            i = numOfObjects + 1;
        }
    }

    if(lastFound == -1)
    {
        tier = theTier;
    }
    else
    {
        objects[lastFound].setLastTier(theTier);
    }
}

void object::setLastId(int theId)
{
    int lastFound = -1;
    for(int i = 0; i <= numOfObjects; i++)
    {
        if(!objects[i].locked)
        {
            lastFound = i;
            i = numOfObjects + 1;
        }
    }

    if(lastFound == -1)
    {
        id = theId;
    }
    else
    {
        objects[lastFound].setLastId(theId);
    }
}

void object::setLastRotation(double theAngle, double theX, double theY, double theZ)
{
    int lastFound = -1;
    for(int i = 0; i <= numOfObjects; i++)
    {
        if(!objects[i].locked)
        {
            lastFound = i;
            i = numOfObjects + 1;
        }
    }

    if(lastFound == -1)
    {
        angle = theAngle;
        rotX = theX;
        rotY = theY;
        rotZ = theZ;
    }
    else
    {
        objects[lastFound].setLastRotation(theAngle, theX, theY, theZ);
    }
}

void object::setLastTranslation(double theX, double theY, double theZ)
{
    int lastFound = -1;
    for(int i = 0; i <= numOfObjects; i++)
    {
        if(!objects[i].locked)
        {
            lastFound = i;
            i = numOfObjects + 1;
        }
    }

    if(lastFound == -1)
    {
        transX = theX;
        transY = theY;
        transZ = theZ;
    }
    else
    {
        objects[lastFound].setLastTranslation(theX, theY, theZ);
    }
}

void object::addLastCoord(char theCoord[])
{
    int lastFound = -1;
    for(int i = 0; i <= numOfObjects; i++)
    {
        if(!objects[i].locked)
        {
            lastFound = i;
            i = numOfObjects + 1;
        }
    }

    if(lastFound == -1)
    {
        string  tempRealString = theCoord;
        coords.push_back(tempRealString);
    }
    else
    {
        objects[lastFound].addLastCoord(theCoord);
    }
}

void object::addLastTextureCoord(char theCoord[])
{
    int lastFound = -1;
    for(int i = 0; i <= numOfObjects; i++)
    {
        if(!objects[i].locked)
        {
            lastFound = i;
            i = numOfObjects + 1;
        }
    }

    if(lastFound == -1)
    {
        string  tempRealString = theCoord;
        textureCoords.push_back(tempRealString);
    }
    else
    {
        objects[lastFound].addLastTextureCoord(theCoord);
    }
}

void object::endIndexShape()
{
    int lastFound = -1;
    for(int i = 0; i <= numOfObjects; i++)
    {
        if(!objects[i].locked)
        {
            lastFound = i;
            i = numOfObjects + 1;
        }
    }

    if(lastFound == -1)
    {
        numOfIndexedShapes = numOfIndexedShapes + 1;
        indexedInShape.push_back(currentShapeIndex);
        currentShapeIndex = -1;
    }
    else
    {
        objects[lastFound].endIndexShape();
    }
}

void object::addLastIndexCoord(int theCoord)
{
    int lastFound = -1;
    for(int i = 0; i <= numOfObjects; i++)
    {
        if(!objects[i].locked)
        {
            lastFound = i;
            i = numOfObjects + 1;
        }
    }

    if(lastFound == -1)
    {
        indexedCoords.push_back(theCoord);
        currentShapeIndex = currentShapeIndex + 1;
    }
    else
    {
        objects[lastFound].addLastIndexCoord(theCoord);
    }
}

void object::addLastIndexTextureCoord(int theCoord)
{
    int lastFound = -1;
    for(int i = 0; i <= numOfObjects; i++)
    {
        if(!objects[i].locked)
        {
            lastFound = i;
            i = numOfObjects + 1;
        }
    }

    if(lastFound == -1)
    {
        indexedTextureCoords.push_back(theCoord);
    }
    else
    {
        objects[lastFound].addLastIndexTextureCoord(theCoord);
    }
}

int object::getTotal()
{
    int total = -1;
    int lastFound = -1;
    for(int i = 0; i <= numOfObjects; i++)
    {
        total = total + objects[i].getTotal();
    }

    total = total + numOfObjects + 1;
    return total;
}

string object::output()
{
    stringstream    theStream;
    if(id != -1)
    {
        theStream <<
            tier <<
            "\n" <<
            id <<
            "\n" <<
            transX <<
            " " <<
            transY <<
            " " <<
            transZ <<
            "\n" <<
            angle <<
            " " <<
            rotX <<
            " " <<
            rotY <<
            " " <<
            rotZ <<
            "\n";
        theStream << numOfIndexedShapes << "\n";
        for(int i = 0; i <= numOfIndexedShapes; i++)
        {
            theStream << indexedInShape[i] << "\n";
            for(int x = 0; x < indexedInShape[i]; x++)
            {
                theStream << coords[indexedCoords[0]] << " ";
                theStream << textureCoords[indexedCoords[0]] << "\n";

                vector<int>::iterator   it = indexedCoords.begin();
                indexedCoords.erase(it);
            }

            /*
             * if(indexedInShape[i] != -1) { theStream << coords[indexedCoords[0]] << "\n";
             * theStream << textureCoords[indexedCoords[0]] << "\n";
             * vector<int>::iterator it=indexedCoords.begin();
             * indexedCoords.erase(it);
             * }
             */
        }
    }

    for(int i = 0; i <= numOfObjects; i++)
    {
        theStream << objects[i].output();
    }

    string  tempString = theStream.str();
    return tempString;
}

mainFile.cpp
Code:
#include <windows.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include "object.hpp"

using namespace std;

char            *fileNameRead;
char            *fileNameWrite;

char            *tempString;
char            tempChar;
ofstream        writeFile;
char            theNumbers[10];

int             tier;

object          parent;

int parseInt(char *theString)
{
    int     theNumber = 0;
    int     theLength = strlen(theString) - 1;
    bool    isNegative = 0;
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

    if(theString[0] == '-')
    {
        isNegative = 1;
        for(int i = 0; i < theLength; i++)
        {
            theString[i] = theString[i + 1];
        }

        theLength = theLength - 1;
    }

    int tempNum = 10;
    for(int x = 0; x <= theLength; x++)
    {
        for(int i = 0; i <= 9; i++)
        {
            if(theString[x] == theNumbers[i])
            {
                for(int z = 0; z <= theLength - x - 1; z++)
                {
                    tempNum = tempNum * 10;
                }

                theNumber = theNumber + (i * (tempNum / 10));
                tempNum = 10;
            }
        }
    }

    if(isNegative)
    {
        theNumber = theNumber * -1;
    }

    return theNumber;
}

int main()
{
    theNumbers[0] = '0';
    theNumbers[1] = '1';
    theNumbers[2] = '2';
    theNumbers[3] = '3';
    theNumbers[4] = '4';
    theNumbers[5] = '5';
    theNumbers[6] = '6';
    theNumbers[7] = '7';
    theNumbers[8] = '8';
    theNumbers[9] = '9';

    string  entered;
    tier = -1;
    cout << "Enter a filename to be converted. \n";
    cin >> entered;

    fileNameRead = new char[entered.length() + 1];
    for(int i = 0; i <= entered.length(); i++)
    {
        fileNameRead[i] = entered[i];
    }

    char    fileNameWrite[entered.length() + 2];
    for(int i = 0; i <= entered.length() - 4; i++)
    {
        fileNameWrite[i] = entered[i];
    }

    fileNameWrite[entered.length() - 3] = 'm';
    fileNameWrite[entered.length() - 2] = 'e';
    fileNameWrite[entered.length() - 1] = 's';
    fileNameWrite[entered.length()] = 'h';
    fileNameWrite[entered.length() + 1] = '\0';

    tempString = new char[100];

    writeFile.open(fileNameWrite);

    FILE    *readFile = fopen(fileNameRead, "r+t");
    if(readFile)
    {
        cout << "opened file " << fileNameRead << "\n";

        bool    done = 0;
        while(fscanf(readFile, "%s", tempString) != -1)
        {
            if(tempString[0] == '#')
            {
                cout << "found '#' (useless)\n";
                while((tempChar = fgetc(readFile)) != '\n')
                { }
            }
            else if(!strcmp(tempString, "DEF"))
            {
                cout << "got DEF\n";

                char    theName[100];
                fscanf(readFile, "%s", theName);
                fscanf(readFile, "%s", tempString);
                if(!strcmp(tempString, "Transform"))
                {
                    while((tempChar = fgetc(readFile)) != SRB)
                    { }

                    tier = tier + 1;
                    cout << "got transform '" << theName << "' at tier " << tier << "\n";
                    parent.makeNew();
                    parent.setLastName(theName);
                    parent.setLastTier(tier);
                    while(!done)
                    {
                        fscanf(readFile, "%s", tempString);
                        if(!strcmp(tempString, "translation"))
                        {
                            double  tempX;
                            double  tempY;
                            double  tempZ;
                            fscanf(readFile, "%lf", &tempX);
                            fscanf(readFile, "%lf", &tempY);
                            fscanf(readFile, "%lf", &tempZ);
                            cout << "translation: " << tempX << ", " << tempY << ", " << tempZ << "\n";
                            parent.setLastTranslation(tempX, tempY, tempZ);
                        }

                        /* end translation if */
                        else if(!strcmp(tempString, "rotation"))
                        {
                            double  angle;
                            double  tempX;
                            double  tempY;
                            double  tempZ;
                            fscanf(readFile, "%lf", &angle);
                            fscanf(readFile, "%lf", &tempX);
                            fscanf(readFile, "%lf", &tempY);
                            fscanf(readFile, "%lf", &tempZ);
                            cout << "rotation: " << angle << ", " << tempX << ", " << tempY << ", " << tempZ << "\n";
                            parent.setLastRotation(angle, tempX, tempY, tempZ);
                        }

                        /* end rotation if */
                        else if(!strcmp(tempString, "children"))
                        {
                            cout << "got child\n";
                            while((tempChar = fgetc(readFile)) != '[')
                            { }

                            done = 1;
                        }

                        /* end children if */
                        else if(!strcmp(tempString, DLB))
                        {
                            done = 1;
                        }

                        /* end ending if */
                        else
                        {
                            cout << "error! tempString: " << tempString << "\n";
                        }

                        /* if error */
                    }

                    done = 0;
                }
                else if(!strcmp(tempString, DLB))
                {
                    done = 1;
                }
                else
                {
                    cout << "error! tempString: " << tempString << "\n";
                }
            }
            else if(!strcmp(tempString, "]"))
            {
                cout << "ended child\n";
            }
            else if(!strcmp(tempString, DLB))
            {
                cout << "ended tranform\n";
                parent.lockLast();
            }
            else if(!strcmp(tempString, "Shape"))
            {
                cout << "got shape\n";
                while((tempChar = fgetc(readFile)) != SRB)
                { }

                while(!done)
                {
                    fscanf(readFile, "%s", tempString);
                    if(!strcmp(tempString, DLB))
                    {
                        done = 1;
                    }
                    else if(!strcmp(tempString, "appearance"))
                    {
                        while(!done)
                        {
                            fscanf(readFile, "%s", tempString);
                            if(!strcmp(tempString, DLB))
                            {
                                done = 1;
                            }
                            else if(!strcmp(tempString, "material"))
                            {
                                while((tempChar = fgetc(readFile)) != SLB)
                                { }
                            }
                        }

                        done = 0;
                    }
                    else if(!strcmp(tempString, "geometry"))
                    {
                        while(!done)
                        {
                            fscanf(readFile, "%s", tempString);
                            if(!strcmp(tempString, "ccw"))
                            {
                                fscanf(readFile, "%s", tempString);
                            }
                            else if(!strcmp(tempString, "solid"))
                            {
                                fscanf(readFile, "%s", tempString);
                            }
                            else if(!strcmp(tempString, "creaseAngle"))
                            {
                                fscanf(readFile, "%s", tempString);
                            }
                            else if(!strcmp(tempString, "coord"))
                            {
                                while((tempChar = fgetc(readFile)) != SRB)
                                { }

                                while(!done)
                                {
                                    fscanf(readFile, "%s", tempString);
                                    if(!strcmp(tempString, DLB))
                                    {
                                        done = 1;
                                    }
                                    else if(!strcmp(tempString, "point"))
                                    {
                                        while((tempChar = fgetc(readFile)) != '[')
                                        { }

                                        char    coordPoint[13];
                                        coordPoint[0] = '\0';

                                        int currentIndex = 0;
                                        tempChar = fgetc(readFile);
                                        if(tempChar != ' ')
                                        {
                                            coordPoint[currentIndex] = tempChar;
                                            currentIndex = currentIndex + 1;
                                        }

                                        bool    wasUseless = 0;
                                        while((tempChar = fgetc(readFile)) != ']')
                                        {
                                            if(tempChar == ',' || tempChar == ' ')
                                            {
                                                coordPoint[currentIndex] = '\0';
                                                currentIndex = 0;
                                                if(!wasUseless)
                                                {
                                                    parent.addLastCoord(coordPoint);
                                                }

                                                wasUseless = 1;
                                            }
                                            else if(tempChar == '\n')
                                            { }
                                            else
                                            {
                                                coordPoint[currentIndex] = tempChar;
                                                currentIndex = currentIndex + 1;
                                                wasUseless = 0;
                                            }
                                        }
                                    }
                                }

                                done = 0;
                            }
                            else
                            {
                                cout << "error! tempString: " << tempString << "\n";
                            }
                        }

                        done = 0;
                    }
                }

                done = 0;
            }
            else
            {
                cout << "error! tempString: " << tempString << "\n";
            }
        }

        done = 0;
    }
    else
    {
        cout << "could not open input file\n";
    }

    writeFile << parent.getTotal() << "\n";
    writeFile << parent.output();

    int theInteger;
    cin >> theInteger;
}

All files (and a .wrl file containing a cube and a cone) can be found at http://www.wyrmmage.com/wrl/

The code isn't very robust, so I'll go ahead and list its most obvious erros here:
If your object name has a '{', '}', '[', or ']' in it, the program will probably die.
Only translations, rotations, and objects are supported (no nurbs, etc.)
If your object is not textured, the program will die.
Lighting, crease angles, materials, etc. will be ignored.

No animation parsing code is in there because it probably wouldn't be very helpful, and I haven't gotten around to writing the code that I'm going to use for animation anyway XD

Hope this helps some people Smile
-wyrmmage

(I haven't compiled this on the Mac, but it should work, and it works fine on Windows)

Worlds at War (Current Project) - http://www.awkward-games.com/forum/
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #2
Indentation!!!!
Quote this message in a reply
Moderator
Posts: 373
Joined: 2006.08
Post: #3
meh, fine...I'll put some indentation in; don't know how you guys can stand that stuff, though.... *shudders* Rasp
-wyrmmage

Worlds at War (Current Project) - http://www.awkward-games.com/forum/
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #4
Um, the *usual* rule with indentation is that the closing brace is at the same level of indentation as the opening one... maybe that's why you have an inexplicable objection to it Rasp
Quote this message in a reply
Moderator
Posts: 373
Joined: 2006.08
Post: #5
ya, I know...I just wrote a simple little script that indents my code for me, that's why it's so bad looking Rasp
I'll see if I can make it so that that doesn't happen.
-wyrmmage

Worlds at War (Current Project) - http://www.awkward-games.com/forum/
Quote this message in a reply
Moderator
Posts: 771
Joined: 2003.04
Post: #6
wyrmmage Wrote:ya, I know...I just wrote a simple little script that indents my code for me, that's why it's so bad looking Rasp
I'll see if I can make it so that that doesn't happen.
-wyrmmage

http://www.hmug.org/man/1/indent.php Wink
Quote this message in a reply
Moderator
Posts: 373
Joined: 2006.08
Post: #7
ok, I indented the script for you guys Rasp
-yrmmage

Worlds at War (Current Project) - http://www.awkward-games.com/forum/
Quote this message in a reply
Post Reply