From 62ecea541d1d7385ba68c0026c8f5113365f7d7b Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 4 Jul 2006 09:13:15 +0000 Subject: [PATCH] From Ulrich Hertlein, updates to DirectX loader --- VisualStudio/osgPlugins/directx/directx.dsp | 16 + src/osgPlugins/directx/GNUmakefile | 4 +- src/osgPlugins/directx/LICENSE | 12 +- .../directx/ReaderWriterDirectX.cpp | 72 +- src/osgPlugins/directx/directx.cpp | 631 ++---------------- src/osgPlugins/directx/directx.h | 164 +---- src/osgPlugins/directx/mesh.cpp | 397 +++++++++++ src/osgPlugins/directx/mesh.h | 106 +++ src/osgPlugins/directx/types.cpp | 242 +++++++ src/osgPlugins/directx/types.h | 131 ++++ 10 files changed, 1018 insertions(+), 757 deletions(-) create mode 100644 src/osgPlugins/directx/mesh.cpp create mode 100644 src/osgPlugins/directx/mesh.h create mode 100644 src/osgPlugins/directx/types.cpp create mode 100644 src/osgPlugins/directx/types.h diff --git a/VisualStudio/osgPlugins/directx/directx.dsp b/VisualStudio/osgPlugins/directx/directx.dsp index 1a83e0b13..7071e98e3 100644 --- a/VisualStudio/osgPlugins/directx/directx.dsp +++ b/VisualStudio/osgPlugins/directx/directx.dsp @@ -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" diff --git a/src/osgPlugins/directx/GNUmakefile b/src/osgPlugins/directx/GNUmakefile index ec6b88e9b..2056e1051 100644 --- a/src/osgPlugins/directx/GNUmakefile +++ b/src/osgPlugins/directx/GNUmakefile @@ -7,7 +7,9 @@ include $(TOPDIR)/Make/makedefs CXXFILES =\ ReaderWriterDirectX.cpp\ - directx.cpp + directx.cpp\ + mesh.cpp\ + types.cpp LIBS += $(OSG_LIBS) $(OTHER_LIBS) diff --git a/src/osgPlugins/directx/LICENSE b/src/osgPlugins/directx/LICENSE index b1e3f5a26..3caebabbb 100644 --- a/src/osgPlugins/directx/LICENSE +++ b/src/osgPlugins/directx/LICENSE @@ -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 diff --git a/src/osgPlugins/directx/ReaderWriterDirectX.cpp b/src/osgPlugins/directx/ReaderWriterDirectX.cpp index 8eb70e731..76d7609c1 100644 --- a/src/osgPlugins/directx/ReaderWriterDirectX.cpp +++ b/src/osgPlugins/directx/ReaderWriterDirectX.cpp @@ -39,6 +39,7 @@ #include #include +#include /** @@ -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 & faces = mesh.getFaces(); + if (faces.size() != meshMaterial->faceIndices.size()) { osg::notify(osg::FATAL)<<"Error: internal error in DirectX .x loader,"<faces.size() == meshMaterial->faceIndices.size()"<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)); } diff --git a/src/osgPlugins/directx/directx.cpp b/src/osgPlugins/directx/directx.cpp index a8ba42ab8..f29a8a8db 100644 --- a/src/osgPlugins/directx/directx.cpp +++ b/src/osgPlugins/directx/directx.cpp @@ -4,7 +4,7 @@ * $Id$ * * Loader for DirectX .x files. - * Copyright (c)2002 Ulrich Hertlein + * Copyright (c)2002-2006 Ulrich Hertlein * * 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& 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 faceNormals; - faceNormals.resize(_mesh->faces.size()); - - unsigned int fi; - for (fi = 0; fi < _mesh->faces.size(); fi++) { - - 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::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 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 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& v, unsigned int count) -{ - char buf[256]; - vector 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 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& v, unsigned int count) -{ - char buf[256]; - vector 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 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 "{ }" for a - // material which was declared globally - // - bool found = false; - if (token.size() > 2) { - std::vector::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& v, unsigned int count) -{ - char buf[256]; - vector 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& v, unsigned int count) -{ - char buf[256]; - vector 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 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 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*/) +{ +} diff --git a/src/osgPlugins/directx/directx.h b/src/osgPlugins/directx/directx.h index 66175c9c5..54444d74d 100644 --- a/src/osgPlugins/directx/directx.h +++ b/src/osgPlugins/directx/directx.h @@ -31,89 +31,11 @@ #include #include +#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 texture; - } Material; - - // MeshFace - typedef std::vector MeshFace; - - // MeshTextureCoords - typedef std::vector MeshTextureCoords; - - // MeshNormals - typedef struct { - std::vector normals; - std::vector faceNormals; - } MeshNormals; - - // MeshVertexColors. - typedef std::vector MeshVertexColors; - - // MeshMaterialList - typedef struct { - std::vector faceIndices; - std::vector material; - } MeshMaterialList; - - // Mesh - typedef struct { - std::vector vertices; - std::vector 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 _globalMaterials; - /// Normals (per-face). - MeshNormals* _normals; - - /// Mesh. - Mesh* _mesh; + /// Meshes. + std::vector _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& v, unsigned int count); - - /// Read 'MeshTextureCoords'. - void readMeshTexCoords(std::ifstream& fin); - - /// Read index list. - void readIndexList(std::ifstream& fin, std::vector& v, unsigned int count); - - /// Parse 'MeshMaterialList'. - void parseMeshMaterialList(std::ifstream& fin); - - /// Read 'Vector'. - void readVector(std::ifstream& fin, std::vector& v, unsigned int count); - - /// Read 'MeshFace'. - void readMeshFace(std::ifstream& fin, std::vector& 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 diff --git a/src/osgPlugins/directx/mesh.cpp b/src/osgPlugins/directx/mesh.cpp new file mode 100644 index 000000000..2e2c9f06b --- /dev/null +++ b/src/osgPlugins/directx/mesh.cpp @@ -0,0 +1,397 @@ +// -*-c++-*- + +/* + * $Id$ + * + * Loader for DirectX .x files. + * Copyright (c)2002-2006 Ulrich Hertlein + * + * 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 + +#include + +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 faceNormals; + faceNormals.resize(_faces.size()); + + unsigned int fi; + for (fi = 0; fi < _faces.size(); fi++) { + + 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 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 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 "{ }" 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::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 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 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; + } + } +} diff --git a/src/osgPlugins/directx/mesh.h b/src/osgPlugins/directx/mesh.h new file mode 100644 index 000000000..53c2cc822 --- /dev/null +++ b/src/osgPlugins/directx/mesh.h @@ -0,0 +1,106 @@ +// -*-c++-*- + +/* + * $Id$ + * + * Loader for DirectX .x files. + * Copyright (c)2002-2006 Ulrich Hertlein + * + * 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 & getVertices() const { + return _vertices; + } + + /// Get MeshFaces. + const std::vector & 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 _vertices; + std::vector _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 diff --git a/src/osgPlugins/directx/types.cpp b/src/osgPlugins/directx/types.cpp new file mode 100644 index 000000000..c98eff324 --- /dev/null +++ b/src/osgPlugins/directx/types.cpp @@ -0,0 +1,242 @@ +// -*-c++-*- + +/* + * $Id$ + * + * Loader for DirectX .x files. + * Copyright (c)2002-2006 Ulrich Hertlein + * + * 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 + +using namespace std; + + +namespace DX { + + // Tokenize a string + void tokenize(const string & str, vector & 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 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 & v, unsigned int count) + { + char buf[256]; + vector 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 & v, unsigned int count) + { + char buf[256]; + vector 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 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 & v, unsigned int count) + { + char buf[256]; + vector 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 & v, unsigned int count) + { + char buf[256]; + vector 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++; + } + } + +}; diff --git a/src/osgPlugins/directx/types.h b/src/osgPlugins/directx/types.h new file mode 100644 index 000000000..e91716216 --- /dev/null +++ b/src/osgPlugins/directx/types.h @@ -0,0 +1,131 @@ +// -*-c++-*- + +/* + * $Id$ + * + * Loader for DirectX .x files. + * Copyright (c)2002-2006 Ulrich Hertlein + * + * 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 +#include +#include + +#include + +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 texture; + } Material; + + // MeshFace + typedef std::vector MeshFace; + + // MeshTextureCoords + typedef std::vector MeshTextureCoords; + + // MeshNormals + typedef struct { + std::vector normals; + std::vector faceNormals; + } MeshNormals; + + // MeshVertexColors. + typedef std::vector MeshVertexColors; + + // MeshMaterialList + typedef struct { + std::vector faceIndices; + std::vector material; + } MeshMaterialList; + + /// Tokenize a string. + extern void tokenize(const std::string& str, std::vector& 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& v, unsigned int count); + + // Read 'Vector' + extern void readVector(std::ifstream& fin, std::vector& v, unsigned int count); + + /// Read index list. + extern void readIndexList(std::ifstream& fin, std::vector& v, unsigned int count); + + /// Read 'MeshFace'. + extern void readMeshFace(std::ifstream& fin, std::vector& v, unsigned int count); + +} // namespace + +#endif