bgfx/3rdparty/openctm/tools/wrl.cpp

306 lines
7.8 KiB
C++
Raw Normal View History

2012-10-07 23:41:18 -04:00
//-----------------------------------------------------------------------------
// Product: OpenCTM tools
// File: wrl.cpp
// Description: Implementation of the VRML 2.0 file format importer/exporter.
//-----------------------------------------------------------------------------
// Copyright (c) 2009-2010 Marcus Geelnard
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//-----------------------------------------------------------------------------
#include <stdexcept>
#include <fstream>
#include <iomanip>
#include <string>
#include <sstream>
#include <vector>
#include <list>
#include "wrl.h"
#include "common.h"
using namespace std;
/// VRML reader class
class VRMLReader {
private:
/// Read buffer
char * mBuffer;
int mBufSize;
int mBufActual;
int mBufPos;
bool mEndOfFile;
/// File comment(s)
string mComment;
/// Read one character from the file stream - via the read buffer
char GetNextChar()
{
if(!mStream)
throw runtime_error("VRML input stream undefined.");
if(mBufPos >= mBufActual)
{
mBufPos = 0;
if(!mStream->eof())
{
mStream->read(mBuffer, mBufSize);
mBufActual = mStream->gcount();
}
else
mBufActual = 0;
mEndOfFile = (mBufActual < 1);
}
if(!mEndOfFile)
{
char c = mBuffer[mBufPos];
++ mBufPos;
return c;
}
else
return ' ';
}
/// Read the next line from file
string GetNextLine()
{
// Read the token (until the next new line)
stringstream sstr;
char c = GetNextChar();
while((!mEndOfFile) && (!IsEOL(c)))
{
sstr << c;
c = GetNextChar();
}
return sstr.str();
}
/// Read a line comment from the stream, and append it to the global
/// comment string
void ReadComment()
{
// Extract the line comment
string newComment = TrimString(GetNextLine());
// Append the line comment to the global comment string
if(newComment.size() > 0)
{
if(mComment.size() > 0)
mComment = mComment + string(" ");
mComment = mComment + newComment;
}
}
/// Read the next token from file (skip comments and whitespaces)
string GetNextToken()
{
char c = ' ';
// Iterate until we find the first character of a token
while(!mEndOfFile)
{
while(!mEndOfFile)
{
c = GetNextChar();
if(!IsWhiteSpace(c))
break;
}
// End of file?
if(mEndOfFile)
return string("");
// Was this a comment?
if(c == '#')
ReadComment();
else
break;
}
// Read the token (until the next white space)
stringstream sstr;
while((!mEndOfFile) && (!IsWhiteSpace(c)))
{
sstr << c;
c = GetNextChar();
}
return sstr.str();
}
public:
/// Constructor
VRMLReader()
{
// Init read buffer
mBufSize = 1024;
mBuffer = new char[mBufSize];
mBufActual = 0;
mBufPos = 0;
mEndOfFile = false;
// Clear state
mStream = 0;
mComment = string("");
}
/// Destructor
~VRMLReader()
{
delete [] mBuffer;
}
/// Read the mesh from a file
void ReadMesh(Mesh * aMesh)
{
// Read the header
string header = GetNextLine();
if(header.substr(0, 10) != string("#VRML V2.0"))
throw runtime_error("Not a valid VRML 2.0 file.");
// Read the rest of the file
while(!mEndOfFile)
{
string token = GetNextToken();
if(token == string("geometry"))
{
token = GetNextToken();
if(token == string("IndexedFaceSet"))
{
// ...FIXME
}
}
}
// Set mesh comment (if any)
aMesh->mComment = mComment;
}
/// Input file stream
ifstream * mStream;
};
/// Import a mesh from a VRML 2.0 file.
void Import_WRL(const char * aFileName, Mesh * aMesh)
{
// FIXME: The import functionality has not yet been fully implemented
throw runtime_error("VRML import is not yet supported.");
// Clear the mesh
aMesh->Clear();
// Open the input file
ifstream f(aFileName, ios::in);
if(f.fail())
throw runtime_error("Could not open input file.");
// Initialize the reader object
VRMLReader reader;
reader.mStream = &f;
// Read the entire file...
reader.ReadMesh(aMesh);
// Close the input file
f.close();
}
/// Export a mesh to a VRML 2.0 file.
void Export_WRL(const char * aFileName, Mesh * aMesh, Options &aOptions)
{
// Open the output file
ofstream f(aFileName, ios::out);
if(f.fail())
throw runtime_error("Could not open output file.");
// Set floating point precision
f << setprecision(8);
// Write VRML file header ID
f << "#VRML V2.0 utf8" << endl;
// Write comment
if(aMesh->mComment.size() > 0)
{
stringstream sstr(aMesh->mComment);
sstr.seekg(0);
while(!sstr.eof())
{
string line;
getline(sstr, line);
line = TrimString(line);
if(line.size() > 0)
f << "# " << line << endl;
}
}
f << endl;
// Write shape header
f << "Group {" << endl;
f << "\tchildren [" << endl;
f << "\t\tShape {" << endl;
f << "\t\t\tappearance Appearance {" << endl;
f << "\t\t\t\tmaterial Material {" << endl;
f << "\t\t\t\t\tdiffuseColor 1.0 1.0 1.0" << endl;
f << "\t\t\t\t\tambientIntensity 0.2" << endl;
f << "\t\t\t\t\tspecularColor 0.8 0.8 0.8" << endl;
f << "\t\t\t\t\tshininess 0.4" << endl;
f << "\t\t\t\t\ttransparency 0" << endl;
f << "\t\t\t\t}" << endl;
f << "\t\t\t}" << endl;
f << "\t\t\tgeometry IndexedFaceSet {" << endl;
f << "\t\t\t\tccw TRUE" << endl;
f << "\t\t\t\tsolid FALSE" << endl;
// Write vertices
f << "\t\t\t\tcoord DEF co Coordinate {" << endl;
f << "\t\t\t\t\tpoint [" << endl;
for(unsigned int i = 0; i < aMesh->mVertices.size(); ++ i)
{
f << "\t\t\t\t\t\t" <<
aMesh->mVertices[i].x << " " <<
aMesh->mVertices[i].y << " " <<
aMesh->mVertices[i].z << "," << endl;
}
f << "\t\t\t\t\t]" << endl;
f << "\t\t\t\t}" << endl;
// Write faces
f << "\t\t\t\tcoordIndex [" << endl;
unsigned int triCount = aMesh->mIndices.size() / 3;
for(unsigned int i = 0; i < triCount; ++ i)
{
f << "\t\t\t\t\t" <<
aMesh->mIndices[i * 3] << ", " <<
aMesh->mIndices[i * 3 + 1] << ", " <<
aMesh->mIndices[i * 3 + 2] << ", -1," << endl;
}
f << "\t\t\t\t]" << endl;
// Write shape footer
f << "\t\t\t}" << endl;
f << "\t\t}" << endl;
f << "\t]" << endl;
f << "}" << endl;
// Close the output file
f.close();
}