From 81bebcd0ec91586729d01a8a41ffe22e1f8561c3 Mon Sep 17 00:00:00 2001 From: aramis_acg Date: Mon, 9 Aug 2010 08:24:16 +0000 Subject: [PATCH] Add basic support for the IZWARE NENDO file format (extension: ndo). The loader has been tested with files in format version 1.0, 1.1 and 1.2. Materials and textures are read but ignored for now. git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@791 67173fc5-114c-0410-ac8e-9d2fd5bffc1f --- code/BaseImporter.cpp | 5 +- code/CMakeLists.txt | 7 + code/CSMLoader.h | 14 +- code/Importer.cpp | 8 +- code/NDOLoader.cpp | 288 +++++++++++++++++++++++++++++++++++ code/NDOLoader.h | 116 ++++++++++++++ code/StringComparison.h | 9 +- workspaces/vc9/assimp.vcproj | 12 ++ 8 files changed, 439 insertions(+), 20 deletions(-) create mode 100644 code/NDOLoader.cpp create mode 100644 code/NDOLoader.h diff --git a/code/BaseImporter.cpp b/code/BaseImporter.cpp index a223a47f0..ae7588faa 100644 --- a/code/BaseImporter.cpp +++ b/code/BaseImporter.cpp @@ -113,8 +113,9 @@ void BaseImporter::SetupProperties(const Importer* pImp) boost::scoped_array _buffer (new char[searchBytes+1 /* for the '\0' */]); char* buffer = _buffer.get(); - unsigned int read = (unsigned int)pStream->Read(buffer,1,searchBytes); - if (!read)return false; + const unsigned int read = pStream->Read(buffer,1,searchBytes); + if (!read) + return false; for (unsigned int i = 0; i < read;++i) buffer[i] = ::tolower(buffer[i]); diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index b6b3d8245..0cbd6191a 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -266,6 +266,11 @@ SOURCE_GROUP( NFF FILES NFFLoader.h ) +SOURCE_GROUP( NDO FILES + NDOLoader.cpp + NDOLoader.h +) + SOURCE_GROUP( OFFFormat FILES OFFLoader.cpp OFFLoader.h @@ -722,6 +727,8 @@ ADD_LIBRARY( assimp SHARED BlenderModifier.h BlenderModifier.cpp Profiler.h + NDOLoader.cpp + NDOLoader.h # Necessary to show the headers in the project when using the VC++ generator: BoostWorkaround/boost/math/common_factor_rt.hpp diff --git a/code/CSMLoader.h b/code/CSMLoader.h index d7c4f1cc9..c84d50287 100644 --- a/code/CSMLoader.h +++ b/code/CSMLoader.h @@ -43,12 +43,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef INCLUDED_AI_CSM_LOADER_H #define INCLUDED_AI_CSM_LOADER_H - -#include "BaseImporter.h" namespace Assimp { // --------------------------------------------------------------------------- -/** @brief Importer class to load MOCAPs in CharacterStudio Motion format. +/** Importer class to load MOCAPs in CharacterStudio Motion format. * * A very rudimentary loader for the moment. No support for the hierarchy, * every marker is returned as child of root. @@ -59,7 +57,6 @@ namespace Assimp { class CSMImporter : public BaseImporter { friend class Importer; - protected: /** Constructor to be privately used by Importer */ CSMImporter(); @@ -68,7 +65,6 @@ protected: ~CSMImporter(); public: - // ------------------------------------------------------------------- bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const; @@ -78,19 +74,15 @@ protected: // ------------------------------------------------------------------- void GetExtensionList(std::set& extensions); - // ------------------------------------------------------------------- void SetupProperties(const Importer* pImp); - // ------------------------------------------------------------------- void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler); private: - -}; // !class CSMImporter - +}; // end of class CSMImporter } // end of namespace Assimp - #endif // AI_AC3DIMPORTER_H_INC + diff --git a/code/Importer.cpp b/code/Importer.cpp index 2ea3fefd8..d70bc3bfe 100644 --- a/code/Importer.cpp +++ b/code/Importer.cpp @@ -180,6 +180,9 @@ using namespace Assimp::Profiling; #ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER # include "Q3BSPFileImporter.h" #endif +#ifndef ASSIMP_BUILD_NO_NDO_IMPORTER +# include "NDOLoader.h" +#endif // ------------------------------------------------------------------------------------------------ // Post processing-Steps @@ -417,7 +420,10 @@ Importer::Importer() // pimpl->mImporter.push_back( new SomImporter()); //#endif #if (!defined ASSIMP_BUILD_NO_Q3BSP_IMPORTER) - pimpl->mImporter.push_back( new Q3BSPFileImporter ); + pimpl->mImporter.push_back( new Q3BSPFileImporter() ); +#endif +#if (!defined ASSIMP_BUILD_NO_NDO_IMPORTER) + pimpl->mImporter.push_back( new NDOImporter() ); #endif // ---------------------------------------------------------------------------- diff --git a/code/NDOLoader.cpp b/code/NDOLoader.cpp new file mode 100644 index 000000000..fc2da4862 --- /dev/null +++ b/code/NDOLoader.cpp @@ -0,0 +1,288 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2009, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +/** @file NDOLoader.cpp + * Implementation of the NDO importer class. + */ + +#include "AssimpPCH.h" +#ifndef AI_BUILD_NO_NDO_IMPORTER +#include "NDOLoader.h" + +using namespace Assimp; +#define for_each BOOST_FOREACH + +// ------------------------------------------------------------------------------------------------ +// Constructor to be privately used by Importer +NDOImporter::NDOImporter() +{} + +// ------------------------------------------------------------------------------------------------ +// Destructor, private as well +NDOImporter::~NDOImporter() +{} + +// ------------------------------------------------------------------------------------------------ +// Returns whether the class can handle the format of the given file. +bool NDOImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const +{ + // check file extension + const std::string extension = GetExtension(pFile); + + if( extension == "ndo") + return true; + + if ((checkSig || !extension.length()) && pIOHandler) { + const char* tokens[] = {"nendo"}; + return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1,5); + } + return false; +} + +// ------------------------------------------------------------------------------------------------ +// Build a string of all file extensions supported +void NDOImporter::GetExtensionList(std::set& extensions) +{ + extensions.insert("ndo"); +} + +// ------------------------------------------------------------------------------------------------ +// Setup configuration properties for the loader +void NDOImporter::SetupProperties(const Importer* pImp) +{ + // nothing to be done for the moment +} + +// ------------------------------------------------------------------------------------------------ +// Imports the given file into the given scene structure. +void NDOImporter::InternReadFile( const std::string& pFile, + aiScene* pScene, IOSystem* pIOHandler) +{ + StreamReaderBE reader(pIOHandler->Open( pFile, "rb")); + + // first 9 bytes are nendo file format ("nendo 1.n") + const char* head = (const char*)reader.GetPtr(); + reader.IncPtr(9); + + if (strncmp("nendo ",head,6)) { + throw DeadlyImportError("Not a Nendo file; magic signature missing"); + } + // check if this is a supported version. if not, continue, too -- users, + // please don't complain if it doesn't work then ... + unsigned int file_format = 12; + if (!strncmp("1.0",head+6,3)) { + file_format = 10; + DefaultLogger::get()->info("NDO file format is 1.0"); + } + else if (!strncmp("1.1",head+6,3)) { + file_format = 11; + DefaultLogger::get()->info("NDO file format is 1.1"); + } + else if (!strncmp("1.2",head+6,3)) { + file_format = 12; + DefaultLogger::get()->info("NDO file format is 1.2"); + } + else { + DefaultLogger::get()->warn(std::string("Unrecognized nendo file format version, continuing happily ... :") + (head+6)); + } + + reader.IncPtr(2); /* skip flags */ + if (file_format >= 12) { + reader.IncPtr(2); + } + unsigned int temp = reader.GetU1(); + + std::vector objects(temp); /* buffer to store all the loaded objects in */ + + // read all objects + for (unsigned int o = 0; o < objects.size(); ++o) { + +// if (file_format < 12) { + if (!reader.GetI1()) { + continue; /* skip over empty object */ + } + // reader.GetI2(); +// } + Object& obj = objects[o]; + + temp = file_format >= 12 ? reader.GetU4() : reader.GetU2(); + head = (const char*)reader.GetPtr(); + reader.IncPtr(temp + 76); /* skip unknown stuff */ + + obj.name = std::string(head, temp); + + // read edge table + temp = file_format >= 12 ? reader.GetU4() : reader.GetU2(); + obj.edges.reserve(temp); + for (unsigned int e = 0; e < temp; ++e) { + + obj.edges.push_back(Edge()); + Edge& edge = obj.edges.back(); + + for (unsigned int i = 0; i< 8; ++i) { + edge.edge[i] = file_format >= 12 ? reader.GetU4() : reader.GetU2(); + } + edge.hard = file_format >= 11 ? reader.GetU1() : 0; + for (unsigned int i = 0; i< 8; ++i) { + edge.color[i] = reader.GetU1(); + } + } + + // read face table + temp = file_format >= 12 ? reader.GetU4() : reader.GetU2(); + obj.faces.reserve(temp); + for (unsigned int e = 0; e < temp; ++e) { + + obj.faces.push_back(Face()); + Face& face = obj.faces.back(); + + face.elem = file_format >= 12 ? reader.GetU4() : reader.GetU2(); + } + + // read vertex table + temp = file_format >= 12 ? reader.GetU4() : reader.GetU2(); + obj.vertices.reserve(temp); + for (unsigned int e = 0; e < temp; ++e) { + + obj.vertices.push_back(Vertex()); + Vertex& v = obj.vertices.back(); + + v.num = file_format >= 12 ? reader.GetU4() : reader.GetU2(); + v.val.x = reader.GetF4(); + v.val.y = reader.GetF4(); + v.val.z = reader.GetF4(); + } + + // read UVs + temp = file_format >= 12 ? reader.GetU4() : reader.GetU2(); + for (unsigned int e = 0; e < temp; ++e) { + file_format >= 12 ? reader.GetU4() : reader.GetU2(); + } + + temp = file_format >= 12 ? reader.GetU4() : reader.GetU2(); + for (unsigned int e = 0; e < temp; ++e) { + file_format >= 12 ? reader.GetU4() : reader.GetU2(); + } + + if (reader.GetU1()) { + const unsigned int x = reader.GetU2(), y = reader.GetU2(); + temp = 0; + while (temp < x*y) { + unsigned int repeat = reader.GetU1(); + reader.GetU1(); + reader.GetU1(); + reader.GetU1(); + temp += repeat; + } + } + } + + // construct a dummy node graph and add all named objects as child nodes + aiNode* root = pScene->mRootNode = new aiNode("$NDODummyRoot"); + aiNode** cc = root->mChildren = new aiNode* [ root->mNumChildren = static_cast( objects.size()) ] (); + pScene->mMeshes = new aiMesh* [ root->mNumChildren] (); + + for_each(const Object& obj,objects) { + aiNode* nd = *cc++ = new aiNode(obj.name); + nd->mParent = root; + + // translated from a python dict() - a vector might be sufficient as well + typedef std::map FaceTable; + FaceTable face_table; + + unsigned int n = 0; + for_each(const Edge& edge, obj.edges) { + + face_table[edge.edge[2]] = n; + face_table[edge.edge[3]] = n; + + ++n; + } + + aiMesh* mesh = new aiMesh(); + aiFace* faces = mesh->mFaces = new aiFace[mesh->mNumFaces=face_table.size()]; + + std::vector vertices; + std::vector indices; + + vertices.reserve(4 * face_table.size()); // arbitrarily choosen + for_each(FaceTable::value_type& v, face_table) { + indices.clear(); + + aiFace& f = *faces++; + + const unsigned int key = v.first; + unsigned int cur_edge = v.second; + while (1) { + unsigned int next_edge, next_vert; + if (key == obj.edges[cur_edge].edge[3]) { + next_edge = obj.edges[cur_edge].edge[5]; + next_vert = obj.edges[cur_edge].edge[1]; + } + else { + next_edge = obj.edges[cur_edge].edge[4]; + next_vert = obj.edges[cur_edge].edge[0]; + } + indices.push_back( vertices.size() ); + vertices.push_back(obj.vertices[ next_vert ].val); + + cur_edge = next_edge; + if (cur_edge == v.second) { + break; + } + } + + f.mIndices = new unsigned int[f.mNumIndices = indices.size()]; + std::copy(indices.begin(),indices.end(),f.mIndices); + } + + mesh->mVertices = new aiVector3D[mesh->mNumVertices = vertices.size()]; + std::copy(vertices.begin(),vertices.end(),mesh->mVertices); + + if (mesh->mNumVertices) { + pScene->mMeshes[pScene->mNumMeshes] = mesh; + + (nd->mMeshes = new unsigned int[nd->mNumMeshes=1])[0]=pScene->mNumMeshes++; + } + } +} + +#endif diff --git a/code/NDOLoader.h b/code/NDOLoader.h new file mode 100644 index 000000000..c14edadce --- /dev/null +++ b/code/NDOLoader.h @@ -0,0 +1,116 @@ +/* +Open Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +/** @file NDOLoader.h + * Declaration of the Nendo importer class. + */ +#ifndef INCLUDED_AI_NDO_LOADER_H +#define INCLUDED_AI_NDO_LOADER_H +namespace Assimp { + +// --------------------------------------------------------------------------- +/** @brief Importer class to load meshes from Nendo. + * + * Basing on + * /blender/release/scripts/nendo_import.py by Anthony D'Agostino. +*/ +class NDOImporter : public BaseImporter +{ + friend class Importer; +protected: + /** Constructor to be privately used by Importer */ + NDOImporter(); + + /** Destructor, private as well */ + ~NDOImporter(); + +public: + + //! Represents a single edge + struct Edge + { + unsigned int edge[8]; + unsigned int hard; + uint8_t color[8]; + }; + + //! Represents a single face + struct Face + { + unsigned int elem; + }; + + struct Vertex + { + unsigned int num; + aiVector3D val; + }; + + //! Represents a single object + struct Object + { + std::string name; + + std::vector edges; + std::vector faces; + std::vector vertices; + }; + + // ------------------------------------------------------------------- + bool CanRead( const std::string& pFile, IOSystem* pIOHandler, + bool checkSig) const; + +protected: + + // ------------------------------------------------------------------- + void GetExtensionList(std::set& extensions); + + // ------------------------------------------------------------------- + void SetupProperties(const Importer* pImp); + + // ------------------------------------------------------------------- + void InternReadFile( const std::string& pFile, aiScene* pScene, + IOSystem* pIOHandler); + +private: + +}; // end of class NDOImporter +} // end of namespace Assimp +#endif // INCLUDED_AI_NDO_LOADER_H diff --git a/code/StringComparison.h b/code/StringComparison.h index 8b7a1c621..1cea4d2f4 100644 --- a/code/StringComparison.h +++ b/code/StringComparison.h @@ -130,20 +130,17 @@ inline int ASSIMP_stricmp(const char *s1, const char *s2) #if (defined _MSC_VER) return ::_stricmp(s1,s2); - #elif defined( __GNUC__ ) - + return ::strcasecmp(s1,s2); - #else + register char c1, c2; - do - { + do { c1 = tolower(*s1++); c2 = tolower(*s2++); } while ( c1 && (c1 == c2) ); - return c1 - c2; #endif } diff --git a/workspaces/vc9/assimp.vcproj b/workspaces/vc9/assimp.vcproj index 8df0fab0f..23ec3e0c7 100644 --- a/workspaces/vc9/assimp.vcproj +++ b/workspaces/vc9/assimp.vcproj @@ -1794,6 +1794,18 @@ > + + + + + +