diff --git a/code/AssetLib/HMP/HMPFileData.h b/code/AssetLib/HMP/HMPFileData.h index 4fc54e2c8..5f6ca4f55 100644 --- a/code/AssetLib/HMP/HMPFileData.h +++ b/code/AssetLib/HMP/HMPFileData.h @@ -49,7 +49,7 @@ namespace HMP { #include #include -// to make it easier for us, we test the magic word against both "endianesses" +// to make it easier for us, we test the magic word against both "endiannesses" #define AI_HMP_MAGIC_NUMBER_BE_4 AI_MAKE_MAGIC("HMP4") #define AI_HMP_MAGIC_NUMBER_LE_4 AI_MAKE_MAGIC("4PMH") diff --git a/code/AssetLib/MD2/MD2FileData.h b/code/AssetLib/MD2/MD2FileData.h index 6c1f7069b..0dba71e56 100644 --- a/code/AssetLib/MD2/MD2FileData.h +++ b/code/AssetLib/MD2/MD2FileData.h @@ -55,7 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { namespace MD2 { -// to make it easier for us, we test the magic word against both "endianesses" +// to make it easier for us, we test the magic word against both "endiannesses" #define AI_MD2_MAGIC_NUMBER_BE AI_MAKE_MAGIC("IDP2") #define AI_MD2_MAGIC_NUMBER_LE AI_MAKE_MAGIC("2PDI") diff --git a/code/AssetLib/MD3/MD3FileData.h b/code/AssetLib/MD3/MD3FileData.h index 4251243b3..86d2647b6 100644 --- a/code/AssetLib/MD3/MD3FileData.h +++ b/code/AssetLib/MD3/MD3FileData.h @@ -62,7 +62,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { namespace MD3 { -// to make it easier for us, we test the magic word against both "endianesses" +// to make it easier for us, we test the magic word against both "endiannesses" #define AI_MD3_MAGIC_NUMBER_BE AI_MAKE_MAGIC("IDP3") #define AI_MD3_MAGIC_NUMBER_LE AI_MAKE_MAGIC("3PDI") diff --git a/code/AssetLib/MDC/MDCFileData.h b/code/AssetLib/MDC/MDCFileData.h index 5d7084b5d..4c5b4127c 100644 --- a/code/AssetLib/MDC/MDCFileData.h +++ b/code/AssetLib/MDC/MDCFileData.h @@ -61,7 +61,7 @@ http://themdcfile.planetwolfenstein.gamespy.com/MDC_File_Format.pdf namespace Assimp { namespace MDC { -// to make it easier for us, we test the magic word against both "endianesses" +// to make it easier for us, we test the magic word against both "endiannesses" #define AI_MDC_MAGIC_NUMBER_BE AI_MAKE_MAGIC("CPDI") #define AI_MDC_MAGIC_NUMBER_LE AI_MAKE_MAGIC("IDPC") diff --git a/code/AssetLib/MDL/MDLFileData.h b/code/AssetLib/MDL/MDLFileData.h index 62117e788..2aff59856 100644 --- a/code/AssetLib/MDL/MDLFileData.h +++ b/code/AssetLib/MDL/MDLFileData.h @@ -67,7 +67,7 @@ namespace Assimp { namespace MDL { // ------------------------------------------------------------------------------------- -// to make it easier for us, we test the magic word against both "endianesses" +// to make it easier for us, we test the magic word against both "endiannesses" // magic bytes used in Quake 1 MDL meshes #define AI_MDL_MAGIC_NUMBER_BE AI_MAKE_MAGIC("IDPO") diff --git a/code/AssetLib/Obj/ObjExporter.cpp b/code/AssetLib/Obj/ObjExporter.cpp index a5d8325fc..7c5c051f3 100644 --- a/code/AssetLib/Obj/ObjExporter.cpp +++ b/code/AssetLib/Obj/ObjExporter.cpp @@ -59,9 +59,9 @@ namespace Assimp { // ------------------------------------------------------------------------------------------------ // Worker function for exporting a scene to Wavefront OBJ. Prototyped and registered in Exporter.cpp -void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) { +void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* props) { // invoke the exporter - ObjExporter exporter(pFile, pScene); + ObjExporter exporter(pFile, pScene, false, props); if (exporter.mOutput.fail() || exporter.mOutputMat.fail()) { throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile)); @@ -86,9 +86,9 @@ void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene // ------------------------------------------------------------------------------------------------ // Worker function for exporting a scene to Wavefront OBJ without the material file. Prototyped and registered in Exporter.cpp -void ExportSceneObjNoMtl(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* ) { +void ExportSceneObjNoMtl(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* props) { // invoke the exporter - ObjExporter exporter(pFile, pScene, true); + ObjExporter exporter(pFile, pScene, true, props); if (exporter.mOutput.fail() || exporter.mOutputMat.fail()) { throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile)); @@ -111,7 +111,7 @@ void ExportSceneObjNoMtl(const char* pFile,IOSystem* pIOSystem, const aiScene* p static const std::string MaterialExt = ".mtl"; // ------------------------------------------------------------------------------------------------ -ObjExporter::ObjExporter(const char* _filename, const aiScene* pScene, bool noMtl) +ObjExporter::ObjExporter(const char* _filename, const aiScene* pScene, bool noMtl, const ExportProperties* props) : filename(_filename) , pScene(pScene) , vn() @@ -130,7 +130,10 @@ ObjExporter::ObjExporter(const char* _filename, const aiScene* pScene, bool noMt mOutputMat.imbue(l); mOutputMat.precision(ASSIMP_AI_REAL_TEXT_PRECISION); - WriteGeometryFile(noMtl); + WriteGeometryFile( + noMtl, + props == nullptr ? true : props->GetPropertyBool("bJoinIdenticalVertices", true) + ); if ( !noMtl ) { WriteMaterialFile(); } @@ -255,14 +258,14 @@ void ObjExporter::WriteMaterialFile() { } } -void ObjExporter::WriteGeometryFile(bool noMtl) { +void ObjExporter::WriteGeometryFile(bool noMtl, bool merge_identical_vertices) { WriteHeader(mOutput); if (!noMtl) mOutput << "mtllib " << GetMaterialLibName() << endl << endl; // collect mesh geometry aiMatrix4x4 mBase; - AddNode(pScene->mRootNode, mBase); + AddNode(pScene->mRootNode, mBase, merge_identical_vertices); // write vertex positions with colors, if any mVpMap.getKeys( vp ); @@ -330,7 +333,7 @@ void ObjExporter::WriteGeometryFile(bool noMtl) { } // ------------------------------------------------------------------------------------------------ -void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat) { +void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat, bool merge_identical_vertices) { mMeshes.emplace_back(); MeshInstance& mesh = mMeshes.back(); @@ -362,13 +365,14 @@ void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4 for(unsigned int a = 0; a < f.mNumIndices; ++a) { const unsigned int idx = f.mIndices[a]; + const unsigned int fi = merge_identical_vertices ? 0 : idx; aiVector3D vert = mat * m->mVertices[idx]; if ( nullptr != m->mColors[ 0 ] ) { aiColor4D col4 = m->mColors[ 0 ][ idx ]; - face.indices[a].vp = mVpMap.getIndex({vert, aiColor3D(col4.r, col4.g, col4.b)}); + face.indices[a].vp = mVpMap.getIndex({vert, aiColor3D(col4.r, col4.g, col4.b), fi}); } else { - face.indices[a].vp = mVpMap.getIndex({vert, aiColor3D(0,0,0)}); + face.indices[a].vp = mVpMap.getIndex({vert, aiColor3D(0,0,0), fi}); } if (m->mNormals) { @@ -388,21 +392,21 @@ void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4 } // ------------------------------------------------------------------------------------------------ -void ObjExporter::AddNode(const aiNode* nd, const aiMatrix4x4& mParent) { +void ObjExporter::AddNode(const aiNode* nd, const aiMatrix4x4& mParent, bool merge_identical_vertices) { const aiMatrix4x4& mAbs = mParent * nd->mTransformation; aiMesh *cm( nullptr ); for(unsigned int i = 0; i < nd->mNumMeshes; ++i) { cm = pScene->mMeshes[nd->mMeshes[i]]; if (nullptr != cm) { - AddMesh(cm->mName, pScene->mMeshes[nd->mMeshes[i]], mAbs); + AddMesh(cm->mName, pScene->mMeshes[nd->mMeshes[i]], mAbs, merge_identical_vertices); } else { - AddMesh(nd->mName, pScene->mMeshes[nd->mMeshes[i]], mAbs); + AddMesh(nd->mName, pScene->mMeshes[nd->mMeshes[i]], mAbs, merge_identical_vertices); } } for(unsigned int i = 0; i < nd->mNumChildren; ++i) { - AddNode(nd->mChildren[i], mAbs); + AddNode(nd->mChildren[i], mAbs, merge_identical_vertices); } } diff --git a/code/AssetLib/Obj/ObjExporter.h b/code/AssetLib/Obj/ObjExporter.h index a64f38f74..4c92aa16f 100644 --- a/code/AssetLib/Obj/ObjExporter.h +++ b/code/AssetLib/Obj/ObjExporter.h @@ -51,6 +51,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include + struct aiScene; struct aiNode; struct aiMesh; @@ -63,7 +65,7 @@ namespace Assimp { class ObjExporter { public: /// Constructor for a specific scene to export - ObjExporter(const char* filename, const aiScene* pScene, bool noMtl=false); + ObjExporter(const char* filename, const aiScene* pScene, bool noMtl=false, const ExportProperties* props = nullptr); ~ObjExporter(); std::string GetMaterialLibName(); std::string GetMaterialLibFileName(); @@ -97,10 +99,10 @@ private: void WriteHeader(std::ostringstream& out); void WriteMaterialFile(); - void WriteGeometryFile(bool noMtl=false); + void WriteGeometryFile(bool noMtl=false, bool merge_identical_vertices = false); std::string GetMaterialName(unsigned int index); - void AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat); - void AddNode(const aiNode* nd, const aiMatrix4x4& mParent); + void AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat, bool merge_identical_vertices); + void AddNode(const aiNode* nd, const aiMatrix4x4& mParent, bool merge_identical_vertices); private: std::string filename; @@ -109,6 +111,7 @@ private: struct vertexData { aiVector3D vp; aiColor3D vc; // OBJ does not support 4D color + uint32_t index = 0; }; std::vector vn, vt; @@ -133,7 +136,7 @@ private: if (a.vc.g > b.vc.g) return false; if (a.vc.b < b.vc.b) return true; if (a.vc.b > b.vc.b) return false; - return false; + return a.index < b.index; } }; diff --git a/doc/dox.h b/doc/dox.h index 1d5f59aa4..2fb127a2b 100644 --- a/doc/dox.h +++ b/doc/dox.h @@ -1545,7 +1545,7 @@ Don't trust the input data! Check all offsets! Mixed stuff for internal use by loaders, mostly documented (most of them are already included by AssimpPCH.h):
  • ByteSwapper (ByteSwapper.h) - manual byte swapping stuff for binary loaders.
  • -
  • StreamReader (StreamReader.h) - safe, endianess-correct, binary reading.
  • +
  • StreamReader (StreamReader.h) - safe, endianness-correct, binary reading.
  • IrrXML (irrXMLWrapper.h) - for XML-parsing (SAX.
  • CommentRemover (RemoveComments.h) - remove single-line and multi-line comments from a text file.
  • fast_atof, strtoul10, strtoul16, SkipSpaceAndLineEnd, SkipToNextToken .. large family of low-level diff --git a/include/assimp/ByteSwapper.h b/include/assimp/ByteSwapper.h index 179f7b555..f738ae701 100644 --- a/include/assimp/ByteSwapper.h +++ b/include/assimp/ByteSwapper.h @@ -263,7 +263,7 @@ struct ByteSwapper { }; // -------------------------------------------------------------------------------------------- -template +template struct Getter { void operator() (T* inout, bool le) { #ifdef AI_BUILD_BIG_ENDIAN @@ -278,12 +278,12 @@ struct Getter { } }; -template -struct Getter { +template +struct Getter { void operator() (T* inout, bool /*le*/) { // static branch - ByteSwapper1)> () (inout); + ByteSwapper1)> () (inout); } }; } // end Intern diff --git a/include/assimp/StreamReader.h b/include/assimp/StreamReader.h index 66e83b7ac..cc74bd652 100644 --- a/include/assimp/StreamReader.h +++ b/include/assimp/StreamReader.h @@ -68,7 +68,7 @@ namespace Assimp { * * XXX switch from unsigned int for size types to size_t? or ptrdiff_t?*/ // -------------------------------------------------------------------------------------------- -template +template class StreamReader { public: using diff = size_t; @@ -84,7 +84,7 @@ public: * reads from the current position to the end of the stream. * @param le If @c RuntimeSwitch is true: specifies whether the * stream is in little endian byte order. Otherwise the - * endianness information is contained in the @c SwapEndianess + * endianness information is contained in the @c SwapEndianness * template parameter and this parameter is meaningless. */ StreamReader(std::shared_ptr stream, bool le = false) : mStream(stream), @@ -291,7 +291,7 @@ public: T f; ::memcpy(&f, mCurrent, sizeof(T)); - Intern::Getter()(&f, mLe); + Intern::Getter()(&f, mLe); mCurrent += sizeof(T); return f; diff --git a/include/assimp/StreamWriter.h b/include/assimp/StreamWriter.h index 7b84789d1..32da6911b 100644 --- a/include/assimp/StreamWriter.h +++ b/include/assimp/StreamWriter.h @@ -65,7 +65,7 @@ namespace Assimp { * stream is to be determined at runtime. */ // -------------------------------------------------------------------------------------------- -template +template class StreamWriter { enum { INITIAL_CAPACITY = 1024 @@ -82,7 +82,7 @@ public: continues at the current position of the stream cursor. * @param le If @c RuntimeSwitch is true: specifies whether the * stream is in little endian byte order. Otherwise the - * endianness information is defined by the @c SwapEndianess + * endianness information is defined by the @c SwapEndianness * template parameter and this parameter is meaningless. */ StreamWriter(std::shared_ptr stream, bool le = false) : stream(stream) @@ -260,7 +260,7 @@ public: /** Generic write method. ByteSwap::Swap(T*) *must* be defined */ template void Put(T f) { - Intern :: Getter() (&f, le); + Intern :: Getter() (&f, le); if (cursor + sizeof(T) >= buffer.size()) { buffer.resize(cursor + sizeof(T)); diff --git a/test/unit/UnitTestFileGenerator.h b/test/unit/UnitTestFileGenerator.h index 2166c6939..93007bad9 100644 --- a/test/unit/UnitTestFileGenerator.h +++ b/test/unit/UnitTestFileGenerator.h @@ -44,9 +44,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#if defined(_MSC_VER) || defined(__MINGW64__) || defined(__MINGW32__) +#define TMP_PATH "./" +#elif defined(__GNUC__) || defined(__clang__) +#define TMP_PATH "/tmp/" +#endif + #if defined(_MSC_VER) #include -#define TMP_PATH "./" inline FILE* MakeTmpFile(char* tmplate) { auto pathtemplate = _mktemp(tmplate); @@ -60,7 +65,6 @@ inline FILE* MakeTmpFile(char* tmplate) return fs; } #elif defined(__GNUC__) || defined(__clang__) -#define TMP_PATH "/tmp/" inline FILE* MakeTmpFile(char* tmplate) { auto fd = mkstemp(tmplate);