From Ulrich Hertlein, updates to DirectX loader

This commit is contained in:
Robert Osfield
2006-07-04 09:13:15 +00:00
parent 5e9076ec10
commit 62ecea541d
10 changed files with 1018 additions and 757 deletions

View File

@@ -161,6 +161,14 @@ SOURCE=..\..\..\src\osgPlugins\directx\directx.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\directx\types.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\directx\mesh.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\directx\ReaderWriterDirectX.cpp
# End Source File
# End Group
@@ -171,6 +179,14 @@ SOURCE=..\..\..\src\osgPlugins\directx\ReaderWriterDirectX.cpp
SOURCE=..\..\..\Src\osgPlugins\directx\directx.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Src\osgPlugins\directx\types.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Src\osgPlugins\directx\mesh.h
# End Source File
# End Group
# Begin Group "Resource Files"

View File

@@ -7,7 +7,9 @@ include $(TOPDIR)/Make/makedefs
CXXFILES =\
ReaderWriterDirectX.cpp\
directx.cpp
directx.cpp\
mesh.cpp\
types.cpp
LIBS += $(OSG_LIBS) $(OTHER_LIBS)

View File

@@ -1,5 +1,5 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
@@ -10,7 +10,7 @@
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
@@ -112,7 +112,7 @@ modification follow. Pay close attention to the difference between a
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
@@ -432,7 +432,7 @@ decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
@@ -455,7 +455,7 @@ FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries

View File

@@ -39,6 +39,7 @@
#include <osgDB/FileUtils>
#include <map>
#include <iostream>
/**
@@ -61,8 +62,11 @@ public:
virtual ReadResult readNode(const std::string& fileName, const osgDB::ReaderWriter::Options* options) const;
private:
osg::Geode* convertFromDX(DX::Object& obj, bool flipTexture, float creaseAngle,
const osgDB::ReaderWriter::Options* options) const;
osg::Group * convertFromDX(DX::Object & obj, bool flipTexture, float creaseAngle,
const osgDB::ReaderWriter::Options * options) const;
osg::Geode * convertFromDX(DX::Mesh & mesh, bool flipTexture, float creaseAngle,
const osgDB::ReaderWriter::Options * options) const;
};
// Register with Registry to instantiate the above reader/writer.
@@ -80,8 +84,6 @@ osgDB::ReaderWriter::ReadResult ReaderWriterDirectX::readNode(const std::string&
osg::notify(osg::INFO) << "ReaderWriterDirectX::readNode(" << fileName.c_str() << ")\n";
// Load DirectX mesh
DX::Object obj;
if (obj.load(fileName.c_str())) {
@@ -102,40 +104,55 @@ osgDB::ReaderWriter::ReadResult ReaderWriterDirectX::readNode(const std::string&
}
}
// Convert to osg::Geode
osg::Geode* geode = convertFromDX(obj, flipTexture, creaseAngle, local_opt.get());
if (!geode)
// Convert to osg::Group
osg::Group* group = convertFromDX(obj, flipTexture, creaseAngle, local_opt.get());
if (!group)
return ReadResult::FILE_NOT_HANDLED;
return geode;
return group;
}
return ReadResult::FILE_NOT_HANDLED;
}
// Convert DirectX mesh to osg::Geode
osg::Geode* ReaderWriterDirectX::convertFromDX(DX::Object& obj,
bool flipTexture, float creaseAngle,
const osgDB::ReaderWriter::Options* options) const
// Convert DirectX object
osg::Group * ReaderWriterDirectX::convertFromDX(DX::Object & obj,
bool flipTexture, float creaseAngle,
const osgDB::ReaderWriter::Options * options) const
{
// Fetch mesh
const DX::Mesh* mesh = obj.getMesh();
if (!mesh)
return NULL;
osg::Group * group = new osg::Group;
const DX::MeshMaterialList* meshMaterial = obj.getMeshMaterialList();
for (unsigned int i = 0; i < obj.getNumMeshes(); ++i) {
//std::cerr << "converting mesh " << i << std::endl;
DX::Mesh & mesh = *obj.getMesh(i);
osg::Geode * geode = convertFromDX(mesh, flipTexture, creaseAngle, options);
if (geode)
group->addChild(geode);
}
return group;
}
// Convert DirectX mesh to osg::Geode
osg::Geode* ReaderWriterDirectX::convertFromDX(DX::Mesh & mesh,
bool flipTexture, float creaseAngle,
const osgDB::ReaderWriter::Options * options) const
{
const DX::MeshMaterialList* meshMaterial = mesh.getMeshMaterialList();
if (!meshMaterial)
return NULL;
const DX::MeshNormals* meshNormals = obj.getMeshNormals();
const DX::MeshNormals* meshNormals = mesh.getMeshNormals();
if (!meshNormals) {
obj.generateNormals(creaseAngle);
meshNormals = obj.getMeshNormals();
mesh.generateNormals(creaseAngle);
meshNormals = mesh.getMeshNormals();
}
//std::cerr << "normals=" << meshNormals << std::endl;
if (!meshNormals)
return NULL;
const DX::MeshTextureCoords* meshTexCoords = obj.getMeshTextureCoords();
const DX::MeshTextureCoords* meshTexCoords = mesh.getMeshTextureCoords();
//std::cerr << "texcoord=" << meshTexCoords << std::endl;
if (!meshTexCoords)
return NULL;
@@ -163,6 +180,8 @@ osg::Geode* ReaderWriterDirectX::convertFromDX(DX::Object& obj,
unsigned int i;
for (i = 0; i < meshMaterial->material.size(); i++) {
//std::cerr << "material " << i << std::endl;
const DX::Material& mtl = meshMaterial->material[i];
osg::StateSet* state = new osg::StateSet;
@@ -201,6 +220,8 @@ osg::Geode* ReaderWriterDirectX::convertFromDX(DX::Object& obj,
unsigned int textureCount = mtl.texture.size();
for (unsigned int j = 0; j < textureCount; j++) {
//std::cerr << "texture " << j << std::endl;
// Share image/texture pairs
osg::Texture2D* texture = texForImage[mtl.texture[j]];
if (!texture) {
@@ -239,7 +260,8 @@ osg::Geode* ReaderWriterDirectX::convertFromDX(DX::Object& obj,
geom->addPrimitiveSet(new osg::DrawArrayLengths(osg::PrimitiveSet::POLYGON));
}
if (mesh->faces.size() != meshMaterial->faceIndices.size())
const std::vector<DX::MeshFace> & faces = mesh.getFaces();
if (faces.size() != meshMaterial->faceIndices.size())
{
osg::notify(osg::FATAL)<<"Error: internal error in DirectX .x loader,"<<std::endl;
osg::notify(osg::FATAL)<<" mesh->faces.size() == meshMaterial->faceIndices.size()"<<std::endl;
@@ -254,7 +276,7 @@ osg::Geode* ReaderWriterDirectX::convertFromDX(DX::Object& obj,
osg::Geometry* geom = geomList[mi];
// #pts of this face
unsigned int np = mesh->faces[i].size();
unsigned int np = faces[i].size();
((osg::DrawArrayLengths*) geom->getPrimitiveSet(0))->push_back(np);
if (np != meshNormals->faceNormals[i].size())
@@ -273,10 +295,10 @@ osg::Geode* ReaderWriterDirectX::convertFromDX(DX::Object& obj,
unsigned int jj = (j > 0 ? np - j : j);
// Vertices
unsigned int vi = mesh->faces[i][jj];
unsigned int vi = faces[i][jj];
if (vertexArray) {
// Transform Xleft/Yup/Zinto to Xleft/Yinto/Zup
const DX::Vector& v = mesh->vertices[vi];
const DX::Vector & v = mesh.getVertices()[vi];
vertexArray->push_back(osg::Vec3(v.x,v.z,v.y));
}

View File

@@ -4,7 +4,7 @@
* $Id$
*
* Loader for DirectX .x files.
* Copyright (c)2002 Ulrich Hertlein <u.hertlein@sandbox.de>
* Copyright (c)2002-2006 Ulrich Hertlein <u.hertlein@sandbox.de>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -39,181 +39,62 @@ using namespace DX;
using namespace std;
// Tokenize a string
static void tokenize(const string& str, vector<string>& tokens,
const string& delimiters = " \t\r\n;,")
{
string::size_type lastPos = str.find_first_not_of(delimiters, 0);
string::size_type pos = str.find_first_of(delimiters, lastPos);
/**********************************************************************
*
* DirectX object.
*
**********************************************************************/
while (string::npos != pos || string::npos != lastPos) {
tokens.push_back(str.substr(lastPos, pos - lastPos));
lastPos = str.find_first_not_of(delimiters, pos);
pos = str.find_first_of(delimiters, lastPos);
}
}
// Constructor
Object::Object()
{
_textureCoords = NULL;
_materialList = NULL;
_normals = NULL;
_mesh = NULL;
}
// Clear object
void Object::clear()
{
if (_textureCoords) {
delete _textureCoords;
_textureCoords = NULL;
}
if (_materialList) {
delete _materialList;
_materialList = NULL;
}
if (_normals) {
delete _normals;
_normals = NULL;
}
if (_mesh) {
delete _mesh;
_mesh = NULL;
for (unsigned int i = 0; i < _meshes.size(); ++i) {
_meshes[i]->clear();
}
_meshes.clear();
}
// Load
bool Object::load(const char* filename)
{
if (!filename)
return false;
// Delete previous
clear();
// Open
ifstream fin(filename);
if (fin.bad()) {
osg::notify(osg::WARN) << "Object::load: Unable to open: " << filename << endl;
return false;
}
// Parse
parseSection(fin);
fin.close();
return true;
}
/*
* Generate per-face normals
*/
bool Object::generateNormals(float /*creaseAngle*/)
bool Object::generateNormals(float creaseAngle)
{
if (!_mesh)
return false;
// Forget old normals
if (_normals) {
delete _normals;
_normals = NULL;
bool result = true;
for (unsigned int i = 0; i < _meshes.size(); ++i) {
result &= _meshes[i]->generateNormals(creaseAngle);
}
cout << "*** generateNormals\n";
return result;
}
/*
* Calculate per-face normals from face vertices.
*/
vector<Vector> faceNormals;
faceNormals.resize(_mesh->faces.size());
unsigned int fi;
for (fi = 0; fi < _mesh->faces.size(); fi++) {
vector<Vector> poly;
unsigned int n = _mesh->faces[fi].size();
if (n < 3)
continue;
for (unsigned int i = 0; i < n; i++) {
unsigned int idx = _mesh->faces[fi][i];
poly.push_back(_mesh->vertices[idx]);
Material * Object::findMaterial(const std::string & name)
{
std::vector<Material>::iterator itr;
for (itr = _globalMaterials.begin(); itr != _globalMaterials.end(); ++itr) {
//cerr << "search=" << name << " have=" << (*itr).name << endl;
if ((*itr).name == name) {
return &*itr;
}
// Edge vectors
Vector e0;
e0.x = poly[1].x - poly[0].x;
e0.y = poly[1].y - poly[0].y;
e0.z = poly[1].z - poly[0].z;
Vector e1;
e1.x = poly[2].x - poly[0].x;
e1.y = poly[2].y - poly[0].y;
e1.z = poly[2].z - poly[0].z;
// Cross-product of e0,e1
Vector normal;
normal.x = e0.y * e1.z - e0.z * e1.y;
normal.y = e0.z * e1.x - e0.x * e1.z;
normal.z = e0.x * e1.y - e0.y * e1.x;
normal.normalize();
// Add to per-face normals
faceNormals[fi] = normal;
}
/*
* Calculate per-vertex normals as average of all per-face normals that
* share this vertex. The index of the vertex normal is identical to the
* vertex index for now. This means each vertex only has a single normal...
*/
_normals = new MeshNormals;
_normals->normals.resize(_mesh->vertices.size());
for (unsigned int vi = 0; vi < _mesh->vertices.size(); vi++) {
Vector normal = { 0.0f, 0.0f, 0.0f };
unsigned int polyCount = 0;
// Collect normals of polygons that share this vertex
for (unsigned int fi = 0; fi < _mesh->faces.size(); fi++)
for (unsigned int i = 0; i < _mesh->faces[fi].size(); i++) {
unsigned int idx = _mesh->faces[fi][i];
if (idx == vi) {
normal.x += faceNormals[fi].x;
normal.y += faceNormals[fi].y;
normal.z += faceNormals[fi].z;
polyCount++;
}
}
//osg::notify(osg::INFO) << "vertex " << vi << " used by " << polyCount << " faces\n";
if (polyCount > 1) {
float polyCountRecip = 1.0f / (float) polyCount;
normal.x *= polyCountRecip;
normal.y *= polyCountRecip;
normal.z *= polyCountRecip;
normal.normalize();
}
// Add vertex normal
_normals->normals[vi] = normal;
}
// Copy face mesh to normals mesh
_normals->faceNormals.resize(_mesh->faces.size());
for (fi = 0; fi < _mesh->faces.size(); fi++)
_normals->faceNormals[fi] = _mesh->faces[fi];
return true;
return 0;
}
@@ -223,436 +104,6 @@ bool Object::generateNormals(float /*creaseAngle*/)
*
**********************************************************************/
// Read 'TextureFilename'
void Object::readTexFilename(ifstream& fin, TextureFilename& texture)
{
char buf[256];
vector<string> token;
//cout << "*** TexFilename\n";
while (fin.getline(buf, sizeof(buf))) {
// Tokenize
token.clear();
tokenize(buf, token);
if (token.size() == 0)
continue;
if (token[0] == "}")
break;
// Strip " if present
std::string line = buf;
std::string::size_type pos = line.find('"');
if (pos != string::npos) {
std::string::size_type end = line.rfind('"');
int len = (end != std::string::npos ? (end-pos-1) : (line.size()-pos));
texture = line.substr(pos+1, len);
}
else
texture = token[0];
//osg::notify(osg::INFO) << "tex=" << texture << endl;
}
}
// Parse 'Material'
void Object::parseMaterial(ifstream& fin, Material& material)
{
char buf[256];
vector<string> token;
unsigned int i = 0;
//cout << "*** Material\n";
while (fin.getline(buf, sizeof(buf))) {
// Tokenize
token.clear();
tokenize(buf, token);
if (token.size() == 0)
continue;
if (token[0] == "}")
break;
if (token[0] == "TextureFilename") {
TextureFilename tf;
readTexFilename(fin, tf);
material.texture.push_back(tf);
//osg::notify(osg::INFO) << "* num tex=" << material.texture.size() << endl;
}
else
switch (i) {
case 0: {
// ColorRGBA
material.faceColor.red = (float) atof(token[0].c_str());
material.faceColor.green = (float) atof(token[1].c_str());
material.faceColor.blue = (float) atof(token[2].c_str());
material.faceColor.alpha = (float) atof(token[3].c_str());
i++;
} break;
case 1: {
// Power
material.power = (float) atof(token[0].c_str());
i++;
} break;
case 2: {
// ColorRGB
material.specularColor.red = (float) atof(token[0].c_str());
material.specularColor.green = (float) atof(token[1].c_str());
material.specularColor.blue = (float) atof(token[2].c_str());
i++;
} break;
case 3: {
// ColorRGB
material.emissiveColor.red = (float) atof(token[0].c_str());
material.emissiveColor.green = (float) atof(token[1].c_str());
material.emissiveColor.blue = (float) atof(token[2].c_str());
i++;
} break;
}
}
}
// Read 'Coords2d'
void Object::readCoords2d(ifstream& fin, vector<Coords2d>& v, unsigned int count)
{
char buf[256];
vector<string> token;
unsigned int i = 0;
//cout << "*** Coords2d\n";
while (i < count && fin.getline(buf, sizeof(buf))) {
// Tokenize
token.clear();
tokenize(buf, token);
if (token.size() == 0)
continue;
Coords2d c;
c.u = (float) atof(token[0].c_str());
c.v = (float) atof(token[1].c_str());
v.push_back(c);
i++;
}
}
// Read 'MeshTextureCoords'
void Object::readMeshTexCoords(ifstream& fin)
{
char buf[256];
vector<string> token;
unsigned int nTextureCoords = 0;
//cout << "*** MeshTextureCoords\n";
while (fin.getline(buf, sizeof(buf))) {
// Tokenize
token.clear();
tokenize(buf, token);
if (token.size() == 0)
continue;
if (strrchr(buf, '}') != 0)
break;
// Create MeshTextureCoords
if (!_textureCoords)
_textureCoords = new MeshTextureCoords;
// Texture coords
nTextureCoords = atoi(token[0].c_str());
readCoords2d(fin, *_textureCoords, nTextureCoords);
if (nTextureCoords != _textureCoords->size())
{
osg::notify(osg::INFO) << "DirectX loader : Error in reading texturcoords." << endl;
delete _textureCoords;
_textureCoords = 0;
}
}
}
// Read index list
void Object::readIndexList(ifstream& fin, vector<unsigned int>& v, unsigned int count)
{
char buf[256];
vector<string> token;
unsigned int i = 0;
//cout << "*** IndexList\n";
while (i < count && fin.getline(buf, sizeof(buf))) {
// Tokenize
token.clear();
tokenize(buf, token);
if (token.size() == 0)
continue;
unsigned int idx = atoi(token[0].c_str());
v.push_back(idx);
i++;
}
}
// Parse 'MeshMaterialList'
void Object::parseMeshMaterialList(ifstream& fin)
{
char buf[256];
vector<string> token;
unsigned int nMaterials = 0, nFaceIndices = 0;
//cout << "*** MeshMaterialList\n";
while (fin.getline(buf, sizeof(buf))) {
// Tokenize
token.clear();
tokenize(buf, token);
if (token.size() == 0)
continue;
//
// dgm - check for "{ <material name> }" for a
// material which was declared globally
//
bool found = false;
if (token.size() > 2) {
std::vector<Material>::iterator itr;
for (itr=_globalMaterials.begin();
itr != _globalMaterials.end();
++itr) {
if ( (*itr).name == token[1]) {
if (!_materialList)
_materialList = new MeshMaterialList;
_materialList->material.push_back(*itr);
found = true;
break;
}
}
}
if (found ) continue;
if (strrchr(buf, '}') != 0)
break;
else if (strrchr(buf, '{') != 0) {
if (token[0] == "Material") {
Material mm;
parseMaterial(fin, mm);
_materialList->material.push_back(mm);
//osg::notify(osg::INFO) << "* num mat=" << _materialList->material.size() << endl;
}
else {
osg::notify(osg::INFO) << "!!! MeshMaterialList: Section " << token[0] << endl;
parseSection(fin);
}
}
else if (nMaterials == 0) {
// Create MeshMaterialList
if (!_materialList)
_materialList = new MeshMaterialList;
// Materials
nMaterials = atoi(token[0].c_str());
//osg::notify(osg::INFO) << "* nMaterials=" << nMaterials << endl;
}
else if (nFaceIndices == 0) {
// Face indices
nFaceIndices = atoi(token[0].c_str());
readIndexList(fin, _materialList->faceIndices, nFaceIndices);
if (nFaceIndices != _materialList->faceIndices.size())
{
osg::notify(osg::WARN) << "DirectX loader : Error in reading face indices" << endl;
}
}
}
if (nMaterials != _materialList->material.size())
{
osg::notify(osg::WARN) << "DirectX loader : Error in reading material list." << endl;
}
}
// Read 'Vector'
void Object::readVector(ifstream& fin, vector<Vector>& v, unsigned int count)
{
char buf[256];
vector<string> token;
unsigned int i = 0;
//cout << "*** Vector\n";
while (i < count && fin.getline(buf, sizeof(buf))) {
// Tokenize
token.clear();
tokenize(buf, token);
if (token.size() == 0)
continue;
Vector vec;
vec.x = (float) atof(token[0].c_str());
vec.y = (float) atof(token[1].c_str());
vec.z = (float) atof(token[2].c_str());
v.push_back(vec);
i++;
}
}
// Read 'MeshFace'
void Object::readMeshFace(ifstream& fin, vector<MeshFace>& v, unsigned int count)
{
char buf[256];
vector<string> token;
unsigned int i = 0;
//cout << "*** MeshFace\n";
while (i < count && fin.getline(buf, sizeof(buf))) {
// Tokenize
token.clear();
tokenize(buf, token);
if (token.size() == 0)
continue;
MeshFace mf;
unsigned int n = atoi(token[0].c_str());
for (unsigned int j = 0; j < n; j++) {
unsigned int idx = atoi(token[j+1].c_str());
mf.push_back(idx);
}
v.push_back(mf);
i++;
}
}
// Parse 'MeshNormals'
void Object::parseMeshNormals(ifstream& fin)
{
char buf[256];
vector<string> token;
unsigned int nNormals = 0, nFaceNormals = 0;
//cout << "*** MeshNormals\n";
while (fin.getline(buf, sizeof(buf))) {
// Tokenize
token.clear();
tokenize(buf, token);
if (token.size() == 0)
continue;
if (strrchr(buf, '}') != 0)
break;
else if (nNormals == 0) {
// Create MeshNormals
if (!_normals)
_normals = new MeshNormals;
// Normals
nNormals = atoi(token[0].c_str());
readVector(fin, _normals->normals, nNormals);
if (nNormals != _normals->normals.size())
{
osg::notify(osg::WARN) << "DirectX loader: Error in reading normals." << endl;
}
#define NORMALIZE_NORMALS
#ifdef NORMALIZE_NORMALS
for (unsigned int i = 0; i < _normals->normals.size(); i++)
_normals->normals[i].normalize();
#endif
}
else if (nFaceNormals == 0) {
// Face normals
nFaceNormals = atoi(token[0].c_str());
readMeshFace(fin, _normals->faceNormals, nFaceNormals);
if (nFaceNormals != _normals->faceNormals.size())
{
osg::notify(osg::WARN) << "DirectX loader: Error in reading face normals." << endl;
}
}
}
}
// Parse 'Mesh'
void Object::parseMesh(ifstream& fin)
{
char buf[256];
vector<string> token;
unsigned int nVertices = 0, nFaces = 0;
//cout << "*** Mesh\n";
while (fin.getline(buf, sizeof(buf))) {
// Tokenize
token.clear();
tokenize(buf, token);
if (token.size() == 0)
continue;
if (strrchr(buf, '}') != 0) {
break;
}
else if (strrchr(buf, '{') != 0) {
if (token[0] == "MeshMaterialList")
parseMeshMaterialList(fin);
else if (token[0] == "MeshNormals")
parseMeshNormals(fin);
else if (token[0] == "MeshTextureCoords")
readMeshTexCoords(fin);
else {
osg::notify(osg::INFO) << "!!! Mesh: Section " << token[0] << endl;
parseSection(fin);
}
}
else if (nVertices == 0) {
// Create mesh
if (!_mesh)
_mesh = new Mesh;
// Vertices
nVertices = atoi(token[0].c_str());
readVector(fin, _mesh->vertices, nVertices);
if (nVertices != _mesh->vertices.size())
{
osg::notify(osg::WARN) << "DirectX loader : Error in reading vertices." << endl;
}
}
else if (nFaces == 0) {
// Faces
nFaces = atoi(token[0].c_str());
readMeshFace(fin, _mesh->faces, nFaces);
if (nFaces != _mesh->faces.size())
{
osg::notify(osg::WARN) << "DirectX loader: Error in reading mesh." << endl;
}
}
else
osg::notify(osg::INFO) << "!!! " << buf << endl;
}
}
// Parse section
void Object::parseSection(ifstream& fin)
{
@@ -662,7 +113,7 @@ void Object::parseSection(ifstream& fin)
while (fin.getline(buf, sizeof(buf))) {
if (strrchr(buf, '}') != 0) {
//osg::notify(osg::INFO) << "!!! End section\n";
//cerr << "!!! End section\n";
break;
}
else if (strrchr(buf, '{') != 0) {
@@ -672,24 +123,38 @@ void Object::parseSection(ifstream& fin)
if (token.size() == 0)
continue;
//osg::notify(osg::INFO) << "!!! Section " << token[0] << endl;
if (token[0] == "Mesh")
parseMesh(fin);
//
//dgm - In later versions of directx files, materials
// can be declared at the top of the file (e.g. globally).
// Keep this list of global materials in "_globalMaterials"
//
if (token[0] == "Mesh") {
// create new mesh
//cerr << "!!! Begin Mesh" << endl;
Mesh * mesh = new Mesh(this);
_meshes.push_back(mesh);
mesh->parseMesh(fin);
}
else if (token[0] == "Material") {
//
// dgm - In later versions of directx files, materials
// can be declared at the top of the file (e.g. globally).
// Keep this list of global materials in "_globalMaterials"
//
Material mm;
if (token.size() > 1 && token[1] != "") {
mm.name = token[1];
}
parseMaterial(fin, mm);
_globalMaterials.push_back(mm);
} else
}
else if (token[0] == "Frame") {
parseFrame(fin);
}
else {
//cerr << "!!! Begin section " << token[0] << endl;
parseSection(fin);
}
}
}
}
// Parse frame
void Object::parseFrame(ifstream& /*fin*/)
{
}

View File

@@ -31,89 +31,11 @@
#include <osg/Export>
#include <osg/Math>
#include "types.h"
#include "mesh.h"
namespace DX {
/*
* DirectX templates
* http://astronomy.swin.edu.au/~pbourke/geomformats/directx/
*/
// Vector
typedef struct {
float x,y,z;
inline void normalize() {
float lenRecip = 1.0f / sqrtf(x * x + y * y + z * z);
x *= lenRecip;
y *= lenRecip;
z *= lenRecip;
}
} Vector;
// Coords2d
typedef struct {
float u,v;
} Coords2d;
// ColorRGBA
typedef struct {
float red,green,blue,alpha;
} ColorRGBA;
// ColorRGB
typedef struct {
float red,green,blue;
} ColorRGB;
// IndexedColor
typedef struct {
unsigned int index;
ColorRGBA indexColor;
} IndexedColor;
// TextureFilename
typedef std::string TextureFilename;
// Material (potentially with multiple textures)
typedef struct {
ColorRGBA faceColor;
float power;
ColorRGB specularColor;
ColorRGB emissiveColor;
//
// dgm - - materials can have names for later reference
//
std::string name;
std::vector<TextureFilename> texture;
} Material;
// MeshFace
typedef std::vector<unsigned int> MeshFace;
// MeshTextureCoords
typedef std::vector<Coords2d> MeshTextureCoords;
// MeshNormals
typedef struct {
std::vector<Vector> normals;
std::vector<MeshFace> faceNormals;
} MeshNormals;
// MeshVertexColors.
typedef std::vector<IndexedColor> MeshVertexColors;
// MeshMaterialList
typedef struct {
std::vector<unsigned int> faceIndices;
std::vector<Material> material;
} MeshMaterialList;
// Mesh
typedef struct {
std::vector<Vector> vertices;
std::vector<MeshFace> faces;
} Mesh;
/**
* DirectX object.
*/
@@ -144,79 +66,37 @@ namespace DX {
*/
bool generateNormals(float creaseAngle = 80.0f);
/// Get MeshTextureCoords.
inline const MeshTextureCoords* getMeshTextureCoords() const {
return _textureCoords;
}
/// Get MeshMaterialList.
inline const MeshMaterialList* getMeshMaterialList() const {
return _materialList;
}
/// Get MeshNormals.
inline const MeshNormals* getMeshNormals() const {
return _normals;
/// Get number of meshes.
inline unsigned int getNumMeshes() const {
return _meshes.size();
}
/// Get Mesh.
inline const Mesh* getMesh() const {
return _mesh;
inline Mesh* getMesh(unsigned int i) {
return _meshes[i];
}
inline const Mesh* getMesh(unsigned int i) const {
return _meshes[i];
}
/// Find global material.
Material * findMaterial(const std::string & name);
/// Parse section until '}'; recurse as needed.
void parseSection(std::ifstream& fin);
private:
/// Texture coordinates (per-vertex).
MeshTextureCoords* _textureCoords;
/// Material list (per-face).
MeshMaterialList* _materialList;
//
// dgm keep list of materials global to the file
//
// dgm - keep list of materials global to the file
std::vector<Material> _globalMaterials;
/// Normals (per-face).
MeshNormals* _normals;
/// Mesh.
Mesh* _mesh;
/// Meshes.
std::vector<Mesh*> _meshes;
/// Clear object.
void clear();
/// Read 'TextureFilename'.
void readTexFilename(std::ifstream& fin, TextureFilename& texture);
/// Parse 'Material'.
void parseMaterial(std::ifstream& fin, Material& material);
/// Read 'Coords2d'.
void readCoords2d(std::ifstream& fin, std::vector<Coords2d>& v, unsigned int count);
/// Read 'MeshTextureCoords'.
void readMeshTexCoords(std::ifstream& fin);
/// Read index list.
void readIndexList(std::ifstream& fin, std::vector<unsigned int>& v, unsigned int count);
/// Parse 'MeshMaterialList'.
void parseMeshMaterialList(std::ifstream& fin);
/// Read 'Vector'.
void readVector(std::ifstream& fin, std::vector<Vector>& v, unsigned int count);
/// Read 'MeshFace'.
void readMeshFace(std::ifstream& fin, std::vector<MeshFace>& v, unsigned int count);
/// Parse 'MeshNormals'.
void parseMeshNormals(std::ifstream& fin);
/// Parse 'Mesh'.
void parseMesh(std::ifstream& fin);
/// Parse section until '}'; recurse as needed.
void parseSection(std::ifstream& fin);
/// Parse frame.
void parseFrame(std::ifstream& fin);
};
} // namespace

View File

@@ -0,0 +1,397 @@
// -*-c++-*-
/*
* $Id$
*
* Loader for DirectX .x files.
* Copyright (c)2002-2006 Ulrich Hertlein <u.hertlein@sandbox.de>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#if defined(_MSC_VER) && (_MSC_VER <= 1200)
#pragma warning (disable : 4786)
#endif
#include "mesh.h"
#include "directx.h"
#include <iostream>
#include <osg/Notify>
using namespace DX;
using namespace std;
/**********************************************************************
*
* DirectX mesh.
*
**********************************************************************/
Mesh::Mesh(Object * obj)
{
_obj = obj;
_normals = 0;
_textureCoords = 0;
_materialList = 0;
}
void Mesh::clear()
{
if (_normals) {
delete _normals;
_normals = 0;
}
if (_textureCoords) {
delete _textureCoords;
_textureCoords = 0;
}
if (_materialList) {
delete _materialList;
_materialList = 0;
}
}
bool Mesh::generateNormals(float /*creaseAngle*/)
{
//cerr << "*** generateNormals\n";
// Forget old normals
if (_normals) {
delete _normals;
_normals = 0;
}
/*
* Calculate per-face normals from face vertices.
*/
vector<Vector> faceNormals;
faceNormals.resize(_faces.size());
unsigned int fi;
for (fi = 0; fi < _faces.size(); fi++) {
vector<Vector> poly;
unsigned int n = _faces[fi].size();
if (n < 3)
continue;
for (unsigned int i = 0; i < n; i++) {
unsigned int idx = _faces[fi][i];
poly.push_back(_vertices[idx]);
}
// Edge vectors
Vector e0;
e0.x = poly[1].x - poly[0].x;
e0.y = poly[1].y - poly[0].y;
e0.z = poly[1].z - poly[0].z;
Vector e1;
e1.x = poly[2].x - poly[0].x;
e1.y = poly[2].y - poly[0].y;
e1.z = poly[2].z - poly[0].z;
// Cross-product of e0,e1
Vector normal;
normal.x = e0.y * e1.z - e0.z * e1.y;
normal.y = e0.z * e1.x - e0.x * e1.z;
normal.z = e0.x * e1.y - e0.y * e1.x;
normal.normalize();
// Add to per-face normals
faceNormals[fi] = normal;
}
/*
* Calculate per-vertex normals as average of all per-face normals that
* share this vertex. The index of the vertex normal is identical to the
* vertex index for now. This means each vertex only has a single normal...
*/
_normals = new MeshNormals;
_normals->normals.resize(_vertices.size());
for (unsigned int vi = 0; vi < _vertices.size(); vi++) {
Vector normal = { 0.0f, 0.0f, 0.0f };
unsigned int polyCount = 0;
// Collect normals of polygons that share this vertex
for (unsigned int fi = 0; fi < _faces.size(); fi++)
for (unsigned int i = 0; i < _faces[fi].size(); i++) {
unsigned int idx = _faces[fi][i];
if (idx == vi) {
normal.x += faceNormals[fi].x;
normal.y += faceNormals[fi].y;
normal.z += faceNormals[fi].z;
polyCount++;
}
}
//osg::notify(osg::INFO) << "vertex " << vi << " used by " << polyCount << " faces\n";
if (polyCount > 1) {
float polyCountRecip = 1.0f / (float) polyCount;
normal.x *= polyCountRecip;
normal.y *= polyCountRecip;
normal.z *= polyCountRecip;
normal.normalize();
}
// Add vertex normal
_normals->normals[vi] = normal;
}
// Copy face mesh to normals mesh
_normals->faceNormals.resize(_faces.size());
for (fi = 0; fi < _faces.size(); fi++)
_normals->faceNormals[fi] = _faces[fi];
return true;
}
// Parse 'Mesh'
void Mesh::parseMesh(ifstream& fin)
{
char buf[256];
vector<string> token;
unsigned int nVertices = 0, nFaces = 0;
//cerr << "*** Mesh\n";
while (fin.getline(buf, sizeof(buf))) {
// Tokenize
token.clear();
tokenize(buf, token);
if (token.size() == 0)
continue;
//cerr << "*** Mesh token=" << token[0] << endl;
if (strrchr(buf, '}') != 0) {
break;
}
else if (strrchr(buf, '{') != 0) {
if (token[0] == "MeshMaterialList")
parseMeshMaterialList(fin);
else if (token[0] == "MeshNormals")
parseMeshNormals(fin);
else if (token[0] == "MeshTextureCoords")
readMeshTexCoords(fin);
else {
//cerr << "!!! Mesh: Begin section " << token[0] << endl;
_obj->parseSection(fin);
}
}
else if (nVertices == 0) {
// Vertices
nVertices = atoi(token[0].c_str());
readVector(fin, _vertices, nVertices);
if (nVertices != _vertices.size())
{
osg::notify(osg::WARN) << "DirectX loader: Error reading vertices; " << _vertices.size() << " instead of " << nVertices << endl;
}
}
else if (nFaces == 0) {
// Faces
nFaces = atoi(token[0].c_str());
readMeshFace(fin, _faces, nFaces);
if (nFaces != _faces.size())
{
osg::notify(osg::WARN) << "DirectX loader: Error reading mesh; " << _faces.size() << " instead of " << nFaces << endl;
}
}
else
osg::notify(osg::INFO) << "!!! " << buf << endl;
}
}
// Parse 'MeshMaterialList'
void Mesh::parseMeshMaterialList(ifstream& fin)
{
char buf[256];
vector<string> token;
unsigned int nMaterials = 0, nFaceIndices = 0;
//cerr << "*** MeshMaterialList\n";
while (fin.getline(buf, sizeof(buf))) {
// Tokenize
token.clear();
tokenize(buf, token);
if (token.size() == 0)
continue;
// dgm - check for "{ <material name> }" for a
// material which was declared globally
#if 1
Material * material = _obj->findMaterial(token[1]);
if (material) {
_materialList->material.push_back(*material);
continue;
}
#else
bool found = false;
if (token.size() > 2) {
std::vector<Material>::iterator itr;
for (itr = _globalMaterials.begin(); itr != _globalMaterials.end(); ++itr) {
if ( (*itr).name == token[1]) {
if (!_materialList)
_materialList = new MeshMaterialList;
_materialList->material.push_back(*itr);
found = true;
break;
}
}
}
if (found)
continue;
#endif
if (strrchr(buf, '}') != 0)
break;
else if (strrchr(buf, '{') != 0) {
if (token[0] == "Material") {
Material mm;
parseMaterial(fin, mm);
_materialList->material.push_back(mm);
//cerr << "num mat=" << _materialList->material.size() << endl;
}
else {
//cerr << "!!! MeshMaterialList: Begin section " << token[0] << endl;
_obj->parseSection(fin);
}
}
else if (nMaterials == 0) {
// Create MeshMaterialList
if (!_materialList)
_materialList = new MeshMaterialList;
// Materials
nMaterials = atoi(token[0].c_str());
//cerr << "expecting num Materials=" << nMaterials << endl;
}
else if (nFaceIndices == 0) {
// Face indices
nFaceIndices = atoi(token[0].c_str());
readIndexList(fin, _materialList->faceIndices, nFaceIndices);
if (nFaceIndices != _materialList->faceIndices.size())
{
osg::notify(osg::WARN) << "DirectX loader: Error reading face indices; " << nFaceIndices << " instead of " << _materialList->faceIndices.size() << endl;
}
}
}
if (nMaterials != _materialList->material.size())
{
osg::notify(osg::WARN) << "DirectX loader: Error reading material list; " << nMaterials << " instead of " << _materialList->material.size() << endl;
}
}
// Parse 'MeshNormals'
void Mesh::parseMeshNormals(ifstream& fin)
{
char buf[256];
vector<string> token;
unsigned int nNormals = 0, nFaceNormals = 0;
//cerr << "*** MeshNormals\n";
while (fin.getline(buf, sizeof(buf))) {
// Tokenize
token.clear();
tokenize(buf, token);
if (token.size() == 0)
continue;
if (strrchr(buf, '}') != 0)
break;
else if (nNormals == 0) {
// Create MeshNormals
if (!_normals)
_normals = new MeshNormals;
// Normals
nNormals = atoi(token[0].c_str());
readVector(fin, _normals->normals, nNormals);
if (nNormals != _normals->normals.size())
{
osg::notify(osg::WARN) << "DirectX loader: Error reading normals; " << nNormals << " instead of " << _normals->normals.size() << endl;
}
#define NORMALIZE_NORMALS
#ifdef NORMALIZE_NORMALS
for (unsigned int i = 0; i < _normals->normals.size(); i++)
_normals->normals[i].normalize();
#endif
}
else if (nFaceNormals == 0) {
// Face normals
nFaceNormals = atoi(token[0].c_str());
readMeshFace(fin, _normals->faceNormals, nFaceNormals);
if (nFaceNormals != _normals->faceNormals.size())
{
osg::notify(osg::WARN) << "DirectX loader: Error reading face normals; " << nFaceNormals << " instead of " << _normals->faceNormals.size() << endl;
}
}
}
}
// Read 'MeshTextureCoords'
void Mesh::readMeshTexCoords(ifstream& fin)
{
char buf[256];
vector<string> token;
unsigned int nTextureCoords = 0;
//cerr << "*** MeshTextureCoords\n";
while (fin.getline(buf, sizeof(buf))) {
// Tokenize
token.clear();
tokenize(buf, token);
if (token.size() == 0)
continue;
if (strrchr(buf, '}') != 0)
break;
// Create MeshTextureCoords
if (!_textureCoords)
_textureCoords = new MeshTextureCoords;
// Texture coords
nTextureCoords = atoi(token[0].c_str());
readCoords2d(fin, *_textureCoords, nTextureCoords);
if (nTextureCoords != _textureCoords->size())
{
osg::notify(osg::INFO) << "DirectX loader: Error reading texcoords; " << _textureCoords->size() << " instead of " << nTextureCoords << endl;
delete _textureCoords;
_textureCoords = 0;
}
}
}

View File

@@ -0,0 +1,106 @@
// -*-c++-*-
/*
* $Id$
*
* Loader for DirectX .x files.
* Copyright (c)2002-2006 Ulrich Hertlein <u.hertlein@sandbox.de>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _MESH_H_
#define _MESH_H_
#include "types.h"
namespace DX {
class Object;
/**
* DirectX mesh.
*/
class Mesh {
public:
Mesh(Object * obj);
virtual ~Mesh() {
clear();
}
void clear();
/**
* Generate per-vertex normals for the mesh.
* @return false if an error occurred, else true.
*/
bool generateNormals(float creaseAngle);
/// Get Vertices.
const std::vector<Vector> & getVertices() const {
return _vertices;
}
/// Get MeshFaces.
const std::vector<MeshFace> & getFaces() const {
return _faces;
}
/// Get MeshTextureCoords.
inline const MeshTextureCoords* getMeshTextureCoords() const {
return _textureCoords;
}
/// Get MeshMaterialList.
inline const MeshMaterialList* getMeshMaterialList() const {
return _materialList;
}
/// Get MeshNormals.
inline const MeshNormals* getMeshNormals() const {
return _normals;
}
/// Parse 'Mesh'.
void parseMesh(std::ifstream& fin);
private:
Object * _obj;
std::vector<Vector> _vertices;
std::vector<MeshFace> _faces;
/// Normals (per-face).
MeshNormals* _normals;
/// Texture coordinates (per-vertex).
MeshTextureCoords* _textureCoords;
/// Materials.
MeshMaterialList* _materialList;
/// Parse 'MeshNormals'.
void parseMeshNormals(std::ifstream& fin);
/// Parse 'MeshMaterialList'.
void parseMeshMaterialList(std::ifstream& fin);
/// Read 'MeshTextureCoords'.
void readMeshTexCoords(std::ifstream& fin);
};
} // namespace
#endif

View File

@@ -0,0 +1,242 @@
// -*-c++-*-
/*
* $Id$
*
* Loader for DirectX .x files.
* Copyright (c)2002-2006 Ulrich Hertlein <u.hertlein@sandbox.de>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#if defined(_MSC_VER) && (_MSC_VER <= 1200)
#pragma warning (disable : 4786)
#endif
#include "types.h"
#include <iostream>
using namespace std;
namespace DX {
// Tokenize a string
void tokenize(const string & str, vector<string> & tokens, const string & delimiters)
{
string::size_type lastPos = str.find_first_not_of(delimiters, 0);
string::size_type pos = str.find_first_of(delimiters, lastPos);
while (string::npos != pos || string::npos != lastPos) {
tokens.push_back(str.substr(lastPos, pos - lastPos));
lastPos = str.find_first_not_of(delimiters, pos);
pos = str.find_first_of(delimiters, lastPos);
}
}
// Read 'TextureFilename'
void readTexFilename(ifstream & fin, TextureFilename & texture)
{
char buf[256];
vector<string> token;
//cerr << "*** TexFilename\n";
while (fin.getline(buf, sizeof(buf))) {
// Tokenize
token.clear();
tokenize(buf, token);
if (token.size() == 0)
continue;
if (token[0] == "}")
break;
// Strip " if present
std::string line = buf;
std::string::size_type pos = line.find('"');
if (pos != string::npos) {
std::string::size_type end = line.rfind('"');
int len = (end != std::string::npos ? (end-pos-1) : (line.size()-pos));
texture = line.substr(pos+1, len);
}
else
texture = token[0];
//cerr << "* tex='" << texture << "'" << endl;
}
}
// Read 'Coords2d'
void readCoords2d(ifstream & fin, vector<Coords2d> & v, unsigned int count)
{
char buf[256];
vector<string> token;
unsigned int i = 0;
//cerr << "*** Coords2d\n";
while (i < count && fin.getline(buf, sizeof(buf))) {
// Tokenize
token.clear();
tokenize(buf, token);
if (token.size() == 0)
continue;
Coords2d c;
c.u = (float) atof(token[0].c_str());
c.v = (float) atof(token[1].c_str());
v.push_back(c);
i++;
}
}
// Read 'Vector'
void readVector(ifstream & fin, vector<Vector> & v, unsigned int count)
{
char buf[256];
vector<string> token;
unsigned int i = 0;
//cerr << "*** Vector\n";
while (i < count && fin.getline(buf, sizeof(buf))) {
// Tokenize
token.clear();
tokenize(buf, token);
if (token.size() == 0)
continue;
Vector vec;
vec.x = (float) atof(token[0].c_str());
vec.y = (float) atof(token[1].c_str());
vec.z = (float) atof(token[2].c_str());
v.push_back(vec);
i++;
}
}
// Parse 'Material'
void parseMaterial(ifstream & fin, Material & material)
{
char buf[256];
vector<string> token;
unsigned int i = 0;
//cerr << "*** Material\n";
while (fin.getline(buf, sizeof(buf))) {
// Tokenize
token.clear();
tokenize(buf, token);
if (token.size() == 0)
continue;
if (token[0] == "}")
break;
if (token[0] == "TextureFilename") {
TextureFilename tf;
readTexFilename(fin, tf);
material.texture.push_back(tf);
//cerr << "* num tex=" << material.texture.size() << endl;
} else {
switch (i) {
case 0: {
// ColorRGBA
material.faceColor.red = (float) atof(token[0].c_str());
material.faceColor.green = (float) atof(token[1].c_str());
material.faceColor.blue = (float) atof(token[2].c_str());
material.faceColor.alpha = (float) atof(token[3].c_str());
i++;
} break;
case 1: {
// Power
material.power = (float) atof(token[0].c_str());
i++;
} break;
case 2: {
// ColorRGB
material.specularColor.red = (float) atof(token[0].c_str());
material.specularColor.green = (float) atof(token[1].c_str());
material.specularColor.blue = (float) atof(token[2].c_str());
i++;
} break;
case 3: {
// ColorRGB
material.emissiveColor.red = (float) atof(token[0].c_str());
material.emissiveColor.green = (float) atof(token[1].c_str());
material.emissiveColor.blue = (float) atof(token[2].c_str());
i++;
} break;
}
}
}
}
// Read index list
void readIndexList(ifstream & fin, vector<unsigned int> & v, unsigned int count)
{
char buf[256];
vector<string> token;
unsigned int i = 0;
//cerr << "*** IndexList\n";
while (i < count && fin.getline(buf, sizeof(buf))) {
// Tokenize
token.clear();
tokenize(buf, token);
if (token.size() == 0)
continue;
unsigned int idx = atoi(token[0].c_str());
v.push_back(idx);
i++;
}
}
// Read 'MeshFace'
void readMeshFace(ifstream & fin, vector<MeshFace> & v, unsigned int count)
{
char buf[256];
vector<string> token;
unsigned int i = 0;
//cerr << "*** MeshFace\n";
while (i < count && fin.getline(buf, sizeof(buf))) {
// Tokenize
token.clear();
tokenize(buf, token);
if (token.size() == 0)
continue;
MeshFace mf;
unsigned int n = atoi(token[0].c_str());
for (unsigned int j = 0; j < n; j++) {
unsigned int idx = atoi(token[j+1].c_str());
mf.push_back(idx);
}
v.push_back(mf);
i++;
}
}
};

View File

@@ -0,0 +1,131 @@
// -*-c++-*-
/*
* $Id$
*
* Loader for DirectX .x files.
* Copyright (c)2002-2006 Ulrich Hertlein <u.hertlein@sandbox.de>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _TYPES_H_
#define _TYPES_H_
#include <string>
#include <vector>
#include <fstream>
#include <osg/Math>
namespace DX {
/*
* DirectX templates
* http://astronomy.swin.edu.au/~pbourke/geomformats/directx/
*/
// Vector
typedef struct {
float x,y,z;
inline void normalize() {
float lenRecip = 1.0f / sqrtf(x * x + y * y + z * z);
x *= lenRecip;
y *= lenRecip;
z *= lenRecip;
}
} Vector;
// Coords2d
typedef struct {
float u,v;
} Coords2d;
// ColorRGBA
typedef struct {
float red,green,blue,alpha;
} ColorRGBA;
// ColorRGB
typedef struct {
float red,green,blue;
} ColorRGB;
// IndexedColor
typedef struct {
unsigned int index;
ColorRGBA indexColor;
} IndexedColor;
// TextureFilename
typedef std::string TextureFilename;
// Material (potentially with multiple textures)
typedef struct {
// dgm - materials can have names for later reference
std::string name;
ColorRGBA faceColor;
float power;
ColorRGB specularColor;
ColorRGB emissiveColor;
std::vector<TextureFilename> texture;
} Material;
// MeshFace
typedef std::vector<unsigned int> MeshFace;
// MeshTextureCoords
typedef std::vector<Coords2d> MeshTextureCoords;
// MeshNormals
typedef struct {
std::vector<Vector> normals;
std::vector<MeshFace> faceNormals;
} MeshNormals;
// MeshVertexColors.
typedef std::vector<IndexedColor> MeshVertexColors;
// MeshMaterialList
typedef struct {
std::vector<unsigned int> faceIndices;
std::vector<Material> material;
} MeshMaterialList;
/// Tokenize a string.
extern void tokenize(const std::string& str, std::vector<std::string>& tokens, const std::string& delimiters = " \t\r\n;,");
/// Parse 'Material'.
extern void parseMaterial(std::ifstream& fin, Material& material);
/// Read 'TextureFilename'.
extern void readTexFilename(std::ifstream& fin, TextureFilename& texture);
/// Read 'Coords2d'.
extern void readCoords2d(std::ifstream& fin, std::vector<Coords2d>& v, unsigned int count);
// Read 'Vector'
extern void readVector(std::ifstream& fin, std::vector<Vector>& v, unsigned int count);
/// Read index list.
extern void readIndexList(std::ifstream& fin, std::vector<unsigned int>& v, unsigned int count);
/// Read 'MeshFace'.
extern void readMeshFace(std::ifstream& fin, std::vector<MeshFace>& v, unsigned int count);
} // namespace
#endif