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
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
-wyrmmage
(I haven't compiled this on the Mac, but it should work, and it works fine on Windows)