diff --git a/.gitignore b/.gitignore index 378eac25d..7fe107086 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ build +.project +*.kdev4* diff --git a/CMakeLists.txt b/CMakeLists.txt index 7a760d2b9..7bb843515 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,7 +18,7 @@ set(LIBASSIMP-DEV_COMPONENT "libassimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_M set(CPACK_COMPONENTS_ALL assimp-bin ${LIBASSIMP_COMPONENT} ${LIBASSIMP-DEV_COMPONENT} assimp-dev) set(ASSIMP_LIBRARY_SUFFIX "" CACHE STRING "Suffix to append to library names") -if( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX AND NOT MINGW ) +if((CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) AND NOT CMAKE_COMPILER_IS_MINGW) add_definitions(-fPIC) # this is a very important switch and some libraries seem now to have it.... # hide all not-exported symbols add_definitions( -fvisibility=hidden -Wall ) diff --git a/code/Assimp.cpp b/code/Assimp.cpp index ad36a1850..b11951854 100644 --- a/code/Assimp.cpp +++ b/code/Assimp.cpp @@ -50,7 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "Importer.h" // ------------------------------------------------------------------------------------------------ -#ifdef AI_C_THREADSAFE +#ifndef ASSIMP_BUILD_SINGLETHREADED # include # include #endif @@ -87,7 +87,7 @@ namespace Assimp } -#ifdef AI_C_THREADSAFE +#ifndef ASSIMP_BUILD_SINGLETHREADED /** Global mutex to manage the access to the logstream map */ static boost::mutex gLogStreamMutex; #endif @@ -104,7 +104,7 @@ public: } ~LogToCallbackRedirector() { -#ifdef AI_C_THREADSAFE +#ifndef ASSIMP_BUILD_SINGLETHREADED boost::mutex::scoped_lock lock(gLogStreamMutex); #endif // (HACK) Check whether the 'stream.user' pointer points to a @@ -172,6 +172,7 @@ const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFl pimpl->mIntProperties = pp->ints; pimpl->mFloatProperties = pp->floats; pimpl->mStringProperties = pp->strings; + pimpl->mMatrixProperties = pp->matrices; } // setup a custom IO system if necessary if (pFS) { @@ -230,6 +231,7 @@ const aiScene* aiImportFileFromMemoryWithProperties( pimpl->mIntProperties = pp->ints; pimpl->mFloatProperties = pp->floats; pimpl->mStringProperties = pp->strings; + pimpl->mMatrixProperties = pp->matrices; } // and have it read the file from the memory buffer @@ -337,7 +339,7 @@ ASSIMP_API void aiAttachLogStream( const aiLogStream* stream ) { ASSIMP_BEGIN_EXCEPTION_REGION(); -#ifdef AI_C_THREADSAFE +#ifndef ASSIMP_BUILD_SINGLETHREADED boost::mutex::scoped_lock lock(gLogStreamMutex); #endif @@ -356,7 +358,7 @@ ASSIMP_API aiReturn aiDetachLogStream( const aiLogStream* stream) { ASSIMP_BEGIN_EXCEPTION_REGION(); -#ifdef AI_C_THREADSAFE +#ifndef ASSIMP_BUILD_SINGLETHREADED boost::mutex::scoped_lock lock(gLogStreamMutex); #endif // find the logstream associated with this data @@ -381,7 +383,7 @@ ASSIMP_API aiReturn aiDetachLogStream( const aiLogStream* stream) ASSIMP_API void aiDetachAllLogStreams(void) { ASSIMP_BEGIN_EXCEPTION_REGION(); -#ifdef AI_C_THREADSAFE +#ifndef ASSIMP_BUILD_SINGLETHREADED boost::mutex::scoped_lock lock(gLogStreamMutex); #endif for (LogStreamMap::iterator it = gActiveLogStreams.begin(); it != gActiveLogStreams.end(); ++it) { @@ -504,6 +506,20 @@ ASSIMP_API void aiSetImportPropertyString(aiPropertyStore* p, const char* szName ASSIMP_END_EXCEPTION_REGION(void); } +// ------------------------------------------------------------------------------------------------ +// Importer::SetPropertyMatrix +ASSIMP_API void aiSetImportPropertyMatrix(aiPropertyStore* p, const char* szName, + const C_STRUCT aiMatrix4x4* mat) +{ + if (!mat) { + return; + } + ASSIMP_BEGIN_EXCEPTION_REGION(); + PropertyMap* pp = reinterpret_cast(p); + SetGenericProperty(pp->matrices,szName,*mat,NULL); + ASSIMP_END_EXCEPTION_REGION(void); +} + // ------------------------------------------------------------------------------------------------ // Rotation matrix to quaternion ASSIMP_API void aiCreateQuaternionFromMatrix(aiQuaternion* quat,const aiMatrix3x3* mat) diff --git a/code/AssimpPCH.cpp b/code/AssimpPCH.cpp index 334fc7eda..f262c8186 100644 --- a/code/AssimpPCH.cpp +++ b/code/AssimpPCH.cpp @@ -69,27 +69,27 @@ ASSIMP_API unsigned int aiGetVersionRevision () } // ------------------------------------------------------------------------------------------------ -aiScene::aiScene() - : mFlags() - , mRootNode() - , mNumMeshes() - , mMeshes() - , mNumMaterials() - , mMaterials() - , mNumAnimations() - , mAnimations() - , mNumTextures() - , mTextures() - , mNumLights() - , mLights() - , mNumCameras() - , mCameras() +ASSIMP_API aiScene::aiScene() + : mFlags(0) + , mRootNode(NULL) + , mNumMeshes(0) + , mMeshes(NULL) + , mNumMaterials(0) + , mMaterials(NULL) + , mNumAnimations(0) + , mAnimations(NULL) + , mNumTextures(0) + , mTextures(NULL) + , mNumLights(0) + , mLights(NULL) + , mNumCameras(0) + , mCameras(NULL) , mPrivate(new Assimp::ScenePrivateData()) { } // ------------------------------------------------------------------------------------------------ -aiScene::~aiScene() +ASSIMP_API aiScene::~aiScene() { // delete all sub-objects recursively delete mRootNode; diff --git a/code/AssimpPCH.h b/code/AssimpPCH.h index f470ca693..c41915e9b 100644 --- a/code/AssimpPCH.h +++ b/code/AssimpPCH.h @@ -74,7 +74,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /* Helper macro to set a pointer to NULL in debug builds */ -#if (defined _DEBUG) +#if (defined ASSIMP_BUILD_DEBUG) # define AI_DEBUG_INVALIDATE_PTR(x) x = NULL; #else # define AI_DEBUG_INVALIDATE_PTR(x) diff --git a/code/BaseImporter.cpp b/code/BaseImporter.cpp index a3ed91acb..b43c1c40f 100644 --- a/code/BaseImporter.cpp +++ b/code/BaseImporter.cpp @@ -379,6 +379,43 @@ void BaseImporter::ConvertToUTF8(std::vector& data) } } +// ------------------------------------------------------------------------------------------------ +// Convert to UTF8 data to ISO-8859-1 +void BaseImporter::ConvertUTF8toISO8859_1(std::string& data) +{ + unsigned int size = data.size(); + unsigned int i = 0, j = 0; + + while(i < size) { + if((unsigned char) data[i] < 0x80) { + data[j] = data[i]; + } else if(i < size - 1) { + if((unsigned char) data[i] == 0xC2) { + data[j] = data[++i]; + } else if((unsigned char) data[i] == 0xC3) { + data[j] = ((unsigned char) data[++i] + 0x40); + } else { + std::stringstream stream; + + stream << "UTF8 code " << std::hex << data[i] << data[i + 1] << " can not be converted into ISA-8859-1."; + + DefaultLogger::get()->error(stream.str()); + + data[j++] = data[i++]; + data[j] = data[i]; + } + } else { + DefaultLogger::get()->error("UTF8 code but only one character remaining"); + + data[j] = data[i]; + } + + i++; j++; + } + + data.resize(j); +} + // ------------------------------------------------------------------------------------------------ void BaseImporter::TextFileToBuffer(IOStream* stream, std::vector& data) @@ -533,7 +570,7 @@ void BatchLoader::LoadAll() for (std::list::iterator it = data->requests.begin();it != data->requests.end(); ++it) { // force validation in debug builds unsigned int pp = (*it).flags; -#ifdef _DEBUG +#ifdef ASSIMP_BUILD_DEBUG pp |= aiProcess_ValidateDataStructure; #endif // setup config properties if necessary @@ -541,6 +578,7 @@ void BatchLoader::LoadAll() pimpl->mFloatProperties = (*it).map.floats; pimpl->mIntProperties = (*it).map.ints; pimpl->mStringProperties = (*it).map.strings; + pimpl->mMatrixProperties = (*it).map.matrices; if (!DefaultLogger::isNullLogger()) { diff --git a/code/BaseImporter.h b/code/BaseImporter.h index 073a476f3..6d3594eaa 100644 --- a/code/BaseImporter.h +++ b/code/BaseImporter.h @@ -331,6 +331,15 @@ public: // static utilities static void ConvertToUTF8( std::vector& data); + // ------------------------------------------------------------------- + /** An utility for all text file loaders. It converts a file from our + * UTF8 character set back to ISO-8859-1. Errors are reported, but ignored. + * + * @param data File buffer to be converted from UTF8 to ISO-8859-1. The buffer + * is resized as appropriate. */ + static void ConvertUTF8toISO8859_1( + std::string& data); + // ------------------------------------------------------------------- /** Utility for text file loaders which copies the contents of the * file into a memory buffer and converts it to our UTF8 diff --git a/code/Bitmap.cpp b/code/Bitmap.cpp new file mode 100644 index 000000000..30b5744ad --- /dev/null +++ b/code/Bitmap.cpp @@ -0,0 +1,145 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2012, assimp 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 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 Bitmap.cpp + * @brief Defines bitmap format helper for textures + * + * Used for file formats which embed their textures into the model file. + */ + +#include "AssimpPCH.h" + +#include "Bitmap.h" + +namespace Assimp { + + void Bitmap::Save(aiTexture* texture, IOStream* file) { + if(file != NULL) { + Header header; + DIB dib; + + dib.size = DIB::dib_size; + dib.width = texture->mWidth; + dib.height = texture->mHeight; + dib.planes = 1; + dib.bits_per_pixel = 8 * mBytesPerPixel; + dib.compression = 0; + dib.image_size = (((dib.width * mBytesPerPixel) + 3) & 0x0000FFFC) * dib.height; + dib.x_resolution = 0; + dib.y_resolution = 0; + dib.nb_colors = 0; + dib.nb_important_colors = 0; + + header.type = 0x4D42; // 'BM' + header.offset = Header::header_size + DIB::dib_size; + header.size = header.offset + dib.image_size; + header.reserved1 = 0; + header.reserved2 = 0; + + WriteHeader(header, file); + WriteDIB(dib, file); + WriteData(texture, file); + } + } + + template + inline std::size_t Copy(uint8_t* data, T& field) { + std::memcpy(data, &AI_BE(field), sizeof(field)); return sizeof(field); + } + + void Bitmap::WriteHeader(Header& header, IOStream* file) { + uint8_t data[Header::header_size]; + + std::size_t offset = 0; + + offset += Copy(&data[offset], header.type); + offset += Copy(&data[offset], header.size); + offset += Copy(&data[offset], header.reserved1); + offset += Copy(&data[offset], header.reserved2); + offset += Copy(&data[offset], header.offset); + + file->Write(data, Header::header_size, 1); + } + + void Bitmap::WriteDIB(DIB& dib, IOStream* file) { + uint8_t data[DIB::dib_size]; + + std::size_t offset = 0; + + offset += Copy(&data[offset], dib.size); + offset += Copy(&data[offset], dib.width); + offset += Copy(&data[offset], dib.height); + offset += Copy(&data[offset], dib.planes); + offset += Copy(&data[offset], dib.bits_per_pixel); + offset += Copy(&data[offset], dib.compression); + offset += Copy(&data[offset], dib.image_size); + offset += Copy(&data[offset], dib.x_resolution); + offset += Copy(&data[offset], dib.y_resolution); + offset += Copy(&data[offset], dib.nb_colors); + offset += Copy(&data[offset], dib.nb_important_colors); + + file->Write(data, DIB::dib_size, 1); + } + + void Bitmap::WriteData(aiTexture* texture, IOStream* file) { + static const std::size_t padding_offset = 4; + static const uint8_t padding_data[padding_offset] = {0x0, 0x0, 0x0, 0x0}; + + unsigned int padding = (padding_offset - ((mBytesPerPixel * texture->mWidth) % padding_offset)) % padding_offset; + uint8_t pixel[mBytesPerPixel]; + + for(std::size_t i = 0; i < texture->mHeight; ++i) { + for(std::size_t j = 0; j < texture->mWidth; ++j) { + const aiTexel& texel = texture->pcData[(texture->mHeight - i - 1) * texture->mWidth + j]; // Bitmap files are stored in bottom-up format + + pixel[0] = texel.r; + pixel[1] = texel.g; + pixel[2] = texel.b; + pixel[3] = texel.a; + + file->Write(pixel, mBytesPerPixel, 1); + } + + file->Write(padding_data, padding, 1); + } + } + +} diff --git a/code/Bitmap.h b/code/Bitmap.h new file mode 100644 index 000000000..36f80363e --- /dev/null +++ b/code/Bitmap.h @@ -0,0 +1,139 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2012, assimp 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 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 Bitmap.h + * @brief Defines bitmap format helper for textures + * + * Used for file formats which embed their textures into the model file. + */ + +#ifndef AI_BITMAP_H_INC +#define AI_BITMAP_H_INC + +namespace Assimp { + +class Bitmap { + + protected: + + struct Header { + + uint16_t type; + + uint32_t size; + + uint16_t reserved1; + + uint16_t reserved2; + + uint32_t offset; + + // We define the struct size because sizeof(Header) might return a wrong result because of structure padding. + // Moreover, we must use this ugly and error prone syntax because Visual Studio neither support constexpr or sizeof(name_of_field). + static const std::size_t header_size = + sizeof(uint16_t) + // type + sizeof(uint32_t) + // size + sizeof(uint16_t) + // reserved1 + sizeof(uint16_t) + // reserved2 + sizeof(uint32_t); // offset + + }; + + struct DIB { + + uint32_t size; + + int32_t width; + + int32_t height; + + uint16_t planes; + + uint16_t bits_per_pixel; + + uint32_t compression; + + uint32_t image_size; + + int32_t x_resolution; + + int32_t y_resolution; + + uint32_t nb_colors; + + uint32_t nb_important_colors; + + // We define the struct size because sizeof(DIB) might return a wrong result because of structure padding. + // Moreover, we must use this ugly and error prone syntax because Visual Studio neither support constexpr or sizeof(name_of_field). + static const std::size_t dib_size = + sizeof(uint32_t) + // size + sizeof(int32_t) + // width + sizeof(int32_t) + // height + sizeof(uint16_t) + // planes + sizeof(uint16_t) + // bits_per_pixel + sizeof(uint32_t) + // compression + sizeof(uint32_t) + // image_size + sizeof(int32_t) + // x_resolution + sizeof(int32_t) + // y_resolution + sizeof(uint32_t) + // nb_colors + sizeof(uint32_t); // nb_important_colors + + }; + + static const std::size_t mBytesPerPixel = 4; + + public: + + static void Save(aiTexture* texture, IOStream* file); + + protected: + + static void WriteHeader(Header& header, IOStream* file); + + static void WriteDIB(DIB& dib, IOStream* file); + + static void WriteData(aiTexture* texture, IOStream* file); + +}; + +} + +#endif // AI_BITMAP_H_INC diff --git a/code/BlenderDNA.h b/code/BlenderDNA.h index b4733f385..7cc2708e4 100644 --- a/code/BlenderDNA.h +++ b/code/BlenderDNA.h @@ -49,7 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "TinyFormatter.h" // enable verbose log output. really verbose, so be careful. -#ifdef _DEBUG +#ifdef ASSIMP_BUILD_DEBUG # define ASSIMP_BUILD_BLENDER_DEBUG #endif diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 29ed3ccff..561797942 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -76,13 +76,13 @@ SOURCE_GROUP(Boost FILES ${Boost_SRCS}) SET( Logging_SRCS ${HEADER_PATH}/DefaultLogger.hpp - ${HEADER_PATH}/IOStream.hpp ${HEADER_PATH}/LogStream.hpp ${HEADER_PATH}/Logger.hpp ${HEADER_PATH}/NullLogger.hpp Win32DebugLogStream.h DefaultLogger.cpp FileLogStream.h + StdOStreamLogStream.h ) SOURCE_GROUP(Logging FILES ${Logging_SRCS}) @@ -107,8 +107,8 @@ SET( Common_SRCS Hash.h Importer.cpp IFF.h + MemoryIOWrapper.h ParsingUtils.h - StdOStreamLogStream.h StreamReader.h StringComparison.h SGSpatialSort.cpp @@ -140,6 +140,8 @@ SET( Common_SRCS TinyFormatter.h Profiler.h LogAux.h + Bitmap.cpp + Bitmap.h ) SOURCE_GROUP(Common FILES ${Common_SRCS}) @@ -461,8 +463,6 @@ SET( PostProcessing_SRCS SortByPTypeProcess.h SplitLargeMeshes.cpp SplitLargeMeshes.h - TerragenLoader.cpp - TerragenLoader.h TextureTransform.cpp TextureTransform.h TriangulateProcess.cpp @@ -520,6 +520,12 @@ SET( STL_SRCS ) SOURCE_GROUP( STL FILES ${STL_SRCS}) +SET( Terragen_SRCS + TerragenLoader.cpp + TerragenLoader.h +) +SOURCE_GROUP( Terragen FILES ${Terragen_SRCS}) + SET( Unreal_SRCS UnrealLoader.cpp UnrealLoader.h @@ -655,6 +661,7 @@ SET( assimp_src ${Raw_SRCS} ${SMD_SRCS} ${STL_SRCS} + ${Terragen_SRCS} ${Unreal_SRCS} ${XFile_SRCS} ${Extra_SRCS} @@ -677,9 +684,14 @@ SET( assimp_src ${PUBLIC_HEADERS} ${COMPILER_HEADERS} + + # Old precompiled header + # (removed because the precompiled header is not updated when visual studio switch configuration which leads to failed compilation. + # Moreover it's a drag to recompile assimp entirely each time a modification is made to one of the included header, which is definitely counter-productive.) + AssimpPCH.cpp ) -ADD_MSVC_PRECOMPILED_HEADER("AssimpPCH.h" "AssimpPCH.cpp" assimp_src) +#ADD_MSVC_PRECOMPILED_HEADER("AssimpPCH.h" "AssimpPCH.cpp" assimp_src) ADD_LIBRARY( assimp ${assimp_src} ) diff --git a/code/ColladaExporter.cpp b/code/ColladaExporter.cpp index 8fba4bf74..cb392acf0 100644 --- a/code/ColladaExporter.cpp +++ b/code/ColladaExporter.cpp @@ -44,6 +44,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER #include "ColladaExporter.h" +#include "Bitmap.h" +#include "fast_atof.h" +#include "SceneCombiner.h" + +#include +#include + using namespace Assimp; namespace Assimp @@ -53,8 +60,25 @@ namespace Assimp // Worker function for exporting a scene to Collada. Prototyped and registered in Exporter.cpp void ExportSceneCollada(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene) { + std::string path = ""; + std::string file = pFile; + + // We need to test both types of folder separators because pIOSystem->getOsSeparator() is not reliable. + // Moreover, the path given by some applications is not even consistent with the OS specific type of separator. + const char* end_path = std::max(strrchr(pFile, '\\'), strrchr(pFile, '/')); + + if(end_path != NULL) { + path = std::string(pFile, end_path + 1 - pFile); + file = file.substr(end_path + 1 - pFile, file.npos); + + std::size_t pos = file.find_last_of('.'); + if(pos != file.npos) { + file = file.substr(0, pos); + } + } + // invoke the exporter - ColladaExporter iDoTheExportThing( pScene); + ColladaExporter iDoTheExportThing( pScene, pIOSystem, path, file); // we're still here - export successfully completed. Write result to the given IOSYstem boost::scoped_ptr outfile (pIOSystem->Open(pFile,"wt")); @@ -71,12 +95,13 @@ void ExportSceneCollada(const char* pFile,IOSystem* pIOSystem, const aiScene* pS // ------------------------------------------------------------------------------------------------ // Constructor for a specific scene to export -ColladaExporter::ColladaExporter( const aiScene* pScene) +ColladaExporter::ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file) : mIOSystem(pIOSystem), mPath(path), mFile(file) { // make sure that all formatting happens using the standard, C locale and not the user's current locale mOutput.imbue( std::locale("C") ); mScene = pScene; + mSceneOwned = false; // set up strings endstr = "\n"; @@ -85,6 +110,15 @@ ColladaExporter::ColladaExporter( const aiScene* pScene) WriteFile(); } +// ------------------------------------------------------------------------------------------------ +// Destructor +ColladaExporter::~ColladaExporter() +{ + if(mSceneOwned) { + delete mScene; + } +} + // ------------------------------------------------------------------------------------------------ // Starts writing the contents void ColladaExporter::WriteFile() @@ -95,9 +129,10 @@ void ColladaExporter::WriteFile() mOutput << "" << endstr; PushTag(); + WriteTextures(); WriteHeader(); - WriteMaterials(); + WriteMaterials(); WriteGeometryLibrary(); WriteSceneLibrary(); @@ -105,7 +140,7 @@ void ColladaExporter::WriteFile() // useless Collada fu at the end, just in case we haven't had enough indirections, yet. mOutput << startstr << "" << endstr; PushTag(); - mOutput << startstr << "" << endstr; + mOutput << startstr << "mRootNode->mName.C_Str()) + "\" />" << endstr; PopTag(); mOutput << startstr << "" << endstr; PopTag(); @@ -116,23 +151,131 @@ void ColladaExporter::WriteFile() // Writes the asset header void ColladaExporter::WriteHeader() { - // Dummy stuff. Nobody actually cares for it anyways + static const float epsilon = 0.000001f; + static const aiQuaternion x_rot(aiMatrix3x3( + 0, -1, 0, + 1, 0, 0, + 0, 0, 1)); + static const aiQuaternion y_rot(aiMatrix3x3( + 1, 0, 0, + 0, 1, 0, + 0, 0, 1)); + static const aiQuaternion z_rot(aiMatrix3x3( + 1, 0, 0, + 0, 0, 1, + 0, -1, 0)); + + static const unsigned int date_nb_chars = 20; + char date_str[date_nb_chars]; + std::time_t date = std::time(NULL); + std::strftime(date_str, date_nb_chars, "%Y-%m-%dT%H:%M:%S", std::localtime(&date)); + + std::string scene_name = mScene->mRootNode->mName.C_Str(); + + aiVector3D scaling; + aiQuaternion rotation; + aiVector3D position; + mScene->mRootNode->mTransformation.Decompose(scaling, rotation, position); + + bool add_root_node = false; + + float scale = 1.0; + if(std::abs(scaling.x - scaling.y) <= epsilon && std::abs(scaling.x - scaling.z) <= epsilon && std::abs(scaling.y - scaling.z) <= epsilon) { + scale = (float) ((((double) scaling.x) + ((double) scaling.y) + ((double) scaling.z)) / 3.0); + } else { + add_root_node = true; + } + + std::string up_axis = "Y_UP"; + if(rotation.Equal(x_rot, epsilon)) { + up_axis = "X_UP"; + } else if(rotation.Equal(y_rot, epsilon)) { + up_axis = "Y_UP"; + } else if(rotation.Equal(z_rot, epsilon)) { + up_axis = "Z_UP"; + } else { + add_root_node = true; + } + + if(! position.Equal(aiVector3D(0, 0, 0))) { + add_root_node = true; + } + + if(mScene->mRootNode->mNumChildren == 0) { + add_root_node = true; + } + + if(add_root_node) { + aiScene* scene; + SceneCombiner::CopyScene(&scene, mScene); + + aiNode* root = new aiNode("Scene"); + + root->mNumChildren = 1; + root->mChildren = new aiNode*[root->mNumChildren]; + + root->mChildren[0] = scene->mRootNode; + scene->mRootNode->mParent = root; + scene->mRootNode = root; + + mScene = scene; + mSceneOwned = true; + + up_axis = "Y_UP"; + scale = 1.0; + } + mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << "" << endstr; PushTag(); - mOutput << startstr << "Someone" << endstr; + mOutput << startstr << "Assimp" << endstr; mOutput << startstr << "Assimp Collada Exporter" << endstr; PopTag(); mOutput << startstr << "" << endstr; - mOutput << startstr << "2000-01-01T23:59:59" << endstr; - mOutput << startstr << "2000-01-01T23:59:59" << endstr; - mOutput << startstr << "" << endstr; - mOutput << startstr << "Y_UP" << endstr; + mOutput << startstr << "" << date_str << "" << endstr; + mOutput << startstr << "" << date_str << "" << endstr; + mOutput << startstr << "" << endstr; + mOutput << startstr << "" << up_axis << "" << endstr; PopTag(); mOutput << startstr << "" << endstr; } +// ------------------------------------------------------------------------------------------------ +// Write the embedded textures +void ColladaExporter::WriteTextures() { + static const unsigned int buffer_size = 1024; + char str[buffer_size]; + + if(mScene->HasTextures()) { + for(unsigned int i = 0; i < mScene->mNumTextures; i++) { + // It would be great to be able to create a directory in portable standard C++, but it's not the case, + // so we just write the textures in the current directory. + + aiTexture* texture = mScene->mTextures[i]; + + ASSIMP_itoa10(str, buffer_size, i + 1); + + std::string name = mFile + "_texture_" + (i < 1000 ? "0" : "") + (i < 100 ? "0" : "") + (i < 10 ? "0" : "") + str + "." + ((const char*) texture->achFormatHint); + + boost::scoped_ptr outfile(mIOSystem->Open(mPath + name, "wb")); + if(outfile == NULL) { + throw DeadlyExportError("could not open output texture file: " + mPath + name); + } + + if(texture->mHeight == 0) { + outfile->Write((void*) texture->pcData, texture->mWidth, 1); + } else { + Bitmap::Save(texture, outfile.get()); + } + + outfile->Flush(); + + textures.insert(std::make_pair(i, name)); + } + } +} + // ------------------------------------------------------------------------------------------------ // Reads a single surface entry from the given material keys void ColladaExporter::ReadMaterialSurface( Surface& poSurface, const aiMaterial* pSrcMat, aiTextureType pTexture, const char* pKey, size_t pType, size_t pIndex) @@ -142,12 +285,39 @@ void ColladaExporter::ReadMaterialSurface( Surface& poSurface, const aiMaterial* aiString texfile; unsigned int uvChannel = 0; pSrcMat->GetTexture( pTexture, 0, &texfile, NULL, &uvChannel); - poSurface.texture = texfile.C_Str(); + + std::string index_str(texfile.C_Str()); + + if(index_str.size() != 0 && index_str[0] == '*') + { + unsigned int index; + + index_str = index_str.substr(1, std::string::npos); + + try { + index = (unsigned int) strtoul10_64(index_str.c_str()); + } catch(std::exception& error) { + throw DeadlyExportError(error.what()); + } + + std::map::const_iterator name = textures.find(index); + + if(name != textures.end()) { + poSurface.texture = name->second; + } else { + throw DeadlyExportError("could not find embedded texture at index " + index_str); + } + } else + { + poSurface.texture = texfile.C_Str(); + } + poSurface.channel = uvChannel; + poSurface.exist = true; } else { if( pKey ) - pSrcMat->Get( pKey, pType, pIndex, poSurface.color); + poSurface.exist = pSrcMat->Get( pKey, pType, pIndex, poSurface.color) == aiReturn_SUCCESS; } } @@ -177,17 +347,19 @@ void ColladaExporter::WriteImageEntry( const Surface& pSurface, const std::strin // Writes a color-or-texture entry into an effect definition void ColladaExporter::WriteTextureColorEntry( const Surface& pSurface, const std::string& pTypeName, const std::string& pImageName) { - mOutput << startstr << "<" << pTypeName << ">" << endstr; - PushTag(); - if( pSurface.texture.empty() ) - { - mOutput << startstr << "" << pSurface.color.r << " " << pSurface.color.g << " " << pSurface.color.b << " " << pSurface.color.a << "" << endstr; - } else - { - mOutput << startstr << "" << endstr; + if(pSurface.exist) { + mOutput << startstr << "<" << pTypeName << ">" << endstr; + PushTag(); + if( pSurface.texture.empty() ) + { + mOutput << startstr << "" << pSurface.color.r << " " << pSurface.color.g << " " << pSurface.color.b << " " << pSurface.color.a << "" << endstr; + } else + { + mOutput << startstr << "" << endstr; + } + PopTag(); + mOutput << startstr << "" << endstr; } - PopTag(); - mOutput << startstr << "" << endstr; } // ------------------------------------------------------------------------------------------------ @@ -219,12 +391,27 @@ void ColladaExporter::WriteTextureParamEntry( const Surface& pSurface, const std } } +// ------------------------------------------------------------------------------------------------ +// Writes a scalar property +void ColladaExporter::WriteFloatEntry( const Property& pProperty, const std::string& pTypeName) +{ + if(pProperty.exist) { + mOutput << startstr << "<" << pTypeName << ">" << endstr; + PushTag(); + mOutput << startstr << "" << pProperty.value << "" << endstr; + PopTag(); + mOutput << startstr << "" << endstr; + } +} + // ------------------------------------------------------------------------------------------------ // Writes the material setup void ColladaExporter::WriteMaterials() { materials.resize( mScene->mNumMaterials); + std::set material_names; + /// collect all materials from the scene size_t numTextures = 0; for( size_t a = 0; a < mScene->mNumMaterials; ++a ) @@ -233,16 +420,30 @@ void ColladaExporter::WriteMaterials() aiString name; if( mat->Get( AI_MATKEY_NAME, name) != aiReturn_SUCCESS ) - name = "mat"; + name = "mat"; materials[a].name = std::string( "m") + boost::lexical_cast (a) + name.C_Str(); for( std::string::iterator it = materials[a].name.begin(); it != materials[a].name.end(); ++it ) { // isalnum on MSVC asserts for code points in [0,255]. Thus prevent unwanted promotion // of char to signed int and take the unsigned char value. - if( !isalnum( static_cast(*it) ) ) { + if( !isalnum( static_cast(*it) ) ) { *it = '_'; } } + aiShadingMode shading; + materials[a].shading_model = "phong"; + if(mat->Get( AI_MATKEY_SHADING_MODEL, shading) == aiReturn_SUCCESS) { + if(shading == aiShadingMode_Phong) { + materials[a].shading_model = "phong"; + } else if(shading == aiShadingMode_Blinn) { + materials[a].shading_model = "blinn"; + } else if(shading == aiShadingMode_NoShading) { + materials[a].shading_model = "constant"; + } else if(shading == aiShadingMode_Gouraud) { + materials[a].shading_model = "lambert"; + } + } + ReadMaterialSurface( materials[a].ambient, mat, aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT); if( !materials[a].ambient.texture.empty() ) numTextures++; ReadMaterialSurface( materials[a].diffuse, mat, aiTextureType_DIFFUSE, AI_MATKEY_COLOR_DIFFUSE); @@ -253,10 +454,15 @@ void ColladaExporter::WriteMaterials() if( !materials[a].emissive.texture.empty() ) numTextures++; ReadMaterialSurface( materials[a].reflective, mat, aiTextureType_REFLECTION, AI_MATKEY_COLOR_REFLECTIVE); if( !materials[a].reflective.texture.empty() ) numTextures++; + ReadMaterialSurface( materials[a].transparent, mat, aiTextureType_OPACITY, AI_MATKEY_COLOR_TRANSPARENT); + if( !materials[a].transparent.texture.empty() ) numTextures++; ReadMaterialSurface( materials[a].normal, mat, aiTextureType_NORMALS, NULL, 0, 0); if( !materials[a].normal.texture.empty() ) numTextures++; - mat->Get( AI_MATKEY_SHININESS, materials[a].shininess); + materials[a].shininess.exist = mat->Get( AI_MATKEY_SHININESS, materials[a].shininess.value) == aiReturn_SUCCESS; + materials[a].transparency.exist = mat->Get( AI_MATKEY_OPACITY, materials[a].transparency.value) == aiReturn_SUCCESS; + materials[a].transparency.value = 1 - materials[a].transparency.value; + materials[a].index_refraction.exist = mat->Get( AI_MATKEY_REFRACTI, materials[a].index_refraction.value) == aiReturn_SUCCESS; } // output textures if present @@ -270,8 +476,9 @@ void ColladaExporter::WriteMaterials() WriteImageEntry( mat.ambient, mat.name + "-ambient-image"); WriteImageEntry( mat.diffuse, mat.name + "-diffuse-image"); WriteImageEntry( mat.specular, mat.name + "-specular-image"); - WriteImageEntry( mat.emissive, mat.name + "-emissive-image"); + WriteImageEntry( mat.emissive, mat.name + "-emission-image"); WriteImageEntry( mat.reflective, mat.name + "-reflective-image"); + WriteImageEntry( mat.transparent, mat.name + "-transparent-image"); WriteImageEntry( mat.normal, mat.name + "-normal-image"); } PopTag(); @@ -293,37 +500,35 @@ void ColladaExporter::WriteMaterials() PushTag(); // write sampler- and surface params for the texture entries - WriteTextureParamEntry( mat.emissive, "emissive", mat.name); + WriteTextureParamEntry( mat.emissive, "emission", mat.name); WriteTextureParamEntry( mat.ambient, "ambient", mat.name); WriteTextureParamEntry( mat.diffuse, "diffuse", mat.name); WriteTextureParamEntry( mat.specular, "specular", mat.name); WriteTextureParamEntry( mat.reflective, "reflective", mat.name); + WriteTextureParamEntry( mat.transparent, "transparent", mat.name); + WriteTextureParamEntry( mat.normal, "normal", mat.name); mOutput << startstr << "" << endstr; PushTag(); - mOutput << startstr << "" << endstr; + mOutput << startstr << "<" << mat.shading_model << ">" << endstr; PushTag(); - WriteTextureColorEntry( mat.emissive, "emission", mat.name + "-emissive-sampler"); + WriteTextureColorEntry( mat.emissive, "emission", mat.name + "-emission-sampler"); WriteTextureColorEntry( mat.ambient, "ambient", mat.name + "-ambient-sampler"); WriteTextureColorEntry( mat.diffuse, "diffuse", mat.name + "-diffuse-sampler"); WriteTextureColorEntry( mat.specular, "specular", mat.name + "-specular-sampler"); - - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << mat.shininess << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - + WriteFloatEntry(mat.shininess, "shininess"); WriteTextureColorEntry( mat.reflective, "reflective", mat.name + "-reflective-sampler"); + WriteTextureColorEntry( mat.transparent, "transparent", mat.name + "-transparent-sampler"); + WriteFloatEntry(mat.transparency, "transparency"); + WriteFloatEntry(mat.index_refraction, "index_of_refraction"); - // deactivated because the Collada spec PHONG model does not allow other textures. - // if( !mat.normal.texture.empty() ) - // WriteTextureColorEntry( mat.normal, "bump", mat.name + "-normal-sampler"); - + if(! mat.normal.texture.empty()) { + WriteTextureColorEntry( mat.normal, "bump", mat.name + "-normal-sampler"); + } PopTag(); - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; PopTag(); mOutput << startstr << "" << endstr; PopTag(); @@ -546,13 +751,16 @@ void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataTy // Writes the scene library void ColladaExporter::WriteSceneLibrary() { + std::string scene_name = mScene->mRootNode->mName.C_Str(); + mOutput << startstr << "" << endstr; PushTag(); - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; PushTag(); // start recursive write at the root node - WriteNode( mScene->mRootNode); + for( size_t a = 0; a < mScene->mRootNode->mNumChildren; ++a ) + WriteNode( mScene->mRootNode->mChildren[a]); PopTag(); mOutput << startstr << "" << endstr; @@ -581,22 +789,22 @@ void ColladaExporter::WriteNode( const aiNode* pNode) for( size_t a = 0; a < pNode->mNumMeshes; ++a ) { const aiMesh* mesh = mScene->mMeshes[pNode->mMeshes[a]]; - // do not instanciate mesh if empty. I wonder how this could happen - if( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 ) - continue; + // do not instanciate mesh if empty. I wonder how this could happen + if( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 ) + continue; mOutput << startstr << "mMeshes[a]) << "\">" << endstr; PushTag(); - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "mMaterialIndex].name << "\" />" << endstr; + mOutput << startstr << "" << endstr; + PushTag(); + mOutput << startstr << "" << endstr; + PushTag(); + mOutput << startstr << "mMaterialIndex].name << "\" />" << endstr; PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); + mOutput << startstr << "" << endstr; + PopTag(); + mOutput << startstr << "" << endstr; + PopTag(); mOutput << startstr << "" << endstr; } diff --git a/code/ColladaExporter.h b/code/ColladaExporter.h index 014e98db4..f96671c40 100644 --- a/code/ColladaExporter.h +++ b/code/ColladaExporter.h @@ -59,7 +59,10 @@ class ColladaExporter { public: /// Constructor for a specific scene to export - ColladaExporter( const aiScene* pScene); + ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file); + + /// Destructor + virtual ~ColladaExporter(); protected: /// Starts writing the contents @@ -68,8 +71,11 @@ protected: /// Writes the asset header void WriteHeader(); - /// Writes the material setup - void WriteMaterials(); + /// Writes the embedded textures + void WriteTextures(); + + /// Writes the material setup + void WriteMaterials(); /// Writes the geometry library void WriteGeometryLibrary(); @@ -101,8 +107,18 @@ public: std::stringstream mOutput; protected: + /// The IOSystem for output + IOSystem* mIOSystem; + + /// Path of the directory where the scene will be exported + const std::string mPath; + + /// Name of the file (without extension) where the scene will be exported + const std::string mFile; + /// The scene to be written const aiScene* mScene; + bool mSceneOwned; /// current line start string, contains the current indentation for simple stream insertion std::string startstr; @@ -112,24 +128,35 @@ protected: // pair of color and texture - texture precedences color struct Surface { + bool exist; aiColor4D color; std::string texture; size_t channel; - Surface() { channel = 0; } + Surface() { exist = false; channel = 0; } + }; + + struct Property + { + bool exist; + float value; + Property() { exist = false; } }; // summarize a material in an convinient way. struct Material { std::string name; - Surface ambient, diffuse, specular, emissive, reflective, normal; - float shininess; /// specular exponent + std::string shading_model; + Surface ambient, diffuse, specular, emissive, reflective, transparent, normal; + Property shininess, transparency, index_refraction; - Material() { shininess = 16.0f; } + Material() {} }; std::vector materials; + std::map textures; + protected: /// Dammit C++ - y u no compile two-pass? No I have to add all methods below the struct definitions /// Reads a single surface entry from the given material keys @@ -140,6 +167,8 @@ protected: void WriteTextureParamEntry( const Surface& pSurface, const std::string& pTypeName, const std::string& pMatName); /// Writes a color-or-texture entry into an effect definition void WriteTextureColorEntry( const Surface& pSurface, const std::string& pTypeName, const std::string& pImageName); + /// Writes a scalar property + void WriteFloatEntry( const Property& pProperty, const std::string& pTypeName); }; } diff --git a/code/DefaultLogger.cpp b/code/DefaultLogger.cpp index f15fd0284..1b9167c55 100644 --- a/code/DefaultLogger.cpp +++ b/code/DefaultLogger.cpp @@ -253,7 +253,7 @@ void DefaultLogger::OnDebug( const char* message ) if ( m_Severity == Logger::NORMAL ) return; - char msg[MAX_LOG_MESSAGE_LENGTH*2]; + char msg[MAX_LOG_MESSAGE_LENGTH + 16]; ::sprintf(msg,"Debug, T%i: %s", GetThreadID(), message ); WriteToStreams( msg, Logger::Debugging ); @@ -263,7 +263,7 @@ void DefaultLogger::OnDebug( const char* message ) // Logs an info void DefaultLogger::OnInfo( const char* message ) { - char msg[MAX_LOG_MESSAGE_LENGTH*2]; + char msg[MAX_LOG_MESSAGE_LENGTH + 16]; ::sprintf(msg,"Info, T%i: %s", GetThreadID(), message ); WriteToStreams( msg , Logger::Info ); @@ -273,7 +273,7 @@ void DefaultLogger::OnInfo( const char* message ) // Logs a warning void DefaultLogger::OnWarn( const char* message ) { - char msg[MAX_LOG_MESSAGE_LENGTH*2]; + char msg[MAX_LOG_MESSAGE_LENGTH + 16]; ::sprintf(msg,"Warn, T%i: %s", GetThreadID(), message ); WriteToStreams( msg, Logger::Warn ); @@ -283,7 +283,7 @@ void DefaultLogger::OnWarn( const char* message ) // Logs an error void DefaultLogger::OnError( const char* message ) { - char msg[MAX_LOG_MESSAGE_LENGTH*2]; + char msg[MAX_LOG_MESSAGE_LENGTH + 16]; ::sprintf(msg,"Error, T%i: %s", GetThreadID(), message ); WriteToStreams( msg, Logger::Err ); diff --git a/code/Exporter.cpp b/code/Exporter.cpp index 306ed824a..7adb9d31d 100644 --- a/code/Exporter.cpp +++ b/code/Exporter.cpp @@ -176,6 +176,8 @@ Exporter :: Exporter() Exporter :: ~Exporter() { FreeBlob(); + + delete pimpl; } diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index d65223d89..f623c3ae7 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -2014,7 +2014,7 @@ private: ai_assert(curves.size()); // sanity check whether the input is ok -#ifdef _DEBUG +#ifdef ASSIMP_BUILD_DEBUG { const Object* target = NULL; BOOST_FOREACH(const AnimationCurveNode* node, curves) { if(!target) { diff --git a/code/FBXParser.cpp b/code/FBXParser.cpp index af0e929bf..fce1143fd 100644 --- a/code/FBXParser.cpp +++ b/code/FBXParser.cpp @@ -565,7 +565,7 @@ void ReadBinaryDataArray(char type, uint32_t count, const char*& data, const cha // terminate zlib inflateEnd(&zstream); } -#ifdef _DEBUG +#ifdef ASSIMP_BUILD_DEBUG else { // runtime check for this happens at tokenization stage ai_assert(false); diff --git a/code/IFCBoolean.cpp b/code/IFCBoolean.cpp index 7330ed940..8573e4d62 100644 --- a/code/IFCBoolean.cpp +++ b/code/IFCBoolean.cpp @@ -221,7 +221,7 @@ bool IntersectsBoundaryProfile( const IfcVector3& e0, const IfcVector3& e1, cons const IfcFloat s = (x*e.y - e.x*y)/det; const IfcFloat t = (x*b.y - b.x*y)/det; -#ifdef _DEBUG +#ifdef ASSIMP_BUILD_DEBUG const IfcVector3 check = b0 + b*s - (e0 + e*t); ai_assert((IfcVector2(check.x,check.y)).SquareLength() < 1e-5); #endif @@ -417,7 +417,7 @@ void ProcessPolygonalBoundedBooleanHalfSpaceDifference(const IfcPolygonalBounded IfcVector3 isectpos; const Intersect isect = extra_point_flag ? Intersect_No : IntersectSegmentPlane(p,n,e0,e1,isectpos); -#ifdef _DEBUG +#ifdef ASSIMP_BUILD_DEBUG if (isect == Intersect_Yes) { const IfcFloat f = fabs((isectpos - p)*n); ai_assert(f < 1e-5); diff --git a/code/IFCCurve.cpp b/code/IFCCurve.cpp index fab256f6a..511b69a2c 100644 --- a/code/IFCCurve.cpp +++ b/code/IFCCurve.cpp @@ -550,7 +550,7 @@ Curve* Curve :: Convert(const IFC::IfcCurve& curve,ConversionData& conv) return NULL; } -#ifdef _DEBUG +#ifdef ASSIMP_BUILD_DEBUG // ------------------------------------------------------------------------------------------------ bool Curve :: InRange(IfcFloat u) const { diff --git a/code/IFCLoader.cpp b/code/IFCLoader.cpp index 9a5f79a5a..f6eedc6cb 100644 --- a/code/IFCLoader.cpp +++ b/code/IFCLoader.cpp @@ -192,24 +192,17 @@ void IFCImporter::InternReadFile( const std::string& pFile, } // search file (same name as the IFCZIP except for the file extension) and place file pointer there - if(UNZ_OK == unzGoToFirstFile(zip)) { do { - // - // get file size, etc. unz_file_info fileInfo; char filename[256]; unzGetCurrentFileInfo( zip , &fileInfo, filename, sizeof(filename), 0, 0, 0, 0 ); - if (GetExtension(filename) != "ifc") { continue; } - uint8_t* buff = new uint8_t[fileInfo.uncompressed_size]; - LogInfo("Decompressing IFCZIP file"); - unzOpenCurrentFile( zip ); const int ret = unzReadCurrentFile( zip, buff, fileInfo.uncompressed_size); size_t filesize = fileInfo.uncompressed_size; @@ -271,7 +264,6 @@ void IFCImporter::InternReadFile( const std::string& pFile, // feed the IFC schema into the reader and pre-parse all lines STEP::ReadFile(*db, schema, types_to_track, inverse_indices_to_track); - const STEP::LazyObject* proj = db->GetObject("ifcproject"); if (!proj) { ThrowException("missing IfcProject entity"); @@ -287,9 +279,9 @@ void IFCImporter::InternReadFile( const std::string& pFile, // in a build with no entities disabled. See // scripts/IFCImporter/CPPGenerator.py // for more information. -#ifdef ASSIMP_IFC_TEST - db->EvaluateAll(); -#endif + #ifdef ASSIMP_IFC_TEST + db->EvaluateAll(); + #endif // do final data copying if (conv.meshes.size()) { @@ -565,21 +557,16 @@ void ProcessProductRepresentation(const IfcProduct& el, aiNode* nd, std::vector< if(!el.Representation) { return; } - - std::vector meshes; - // we want only one representation type, so bring them in a suitable order (i.e try those // that look as if we could read them quickly at first). This way of reading // representation is relatively generic and allows the concrete implementations // for the different representation types to make some sensible choices what // to load and what not to load. const STEP::ListOf< STEP::Lazy< IfcRepresentation >, 1, 0 >& src = el.Representation.Get()->Representations; - std::vector repr_ordered(src.size()); std::copy(src.begin(),src.end(),repr_ordered.begin()); std::sort(repr_ordered.begin(),repr_ordered.end(),RateRepresentationPredicate()); - BOOST_FOREACH(const IfcRepresentation* repr, repr_ordered) { bool res = false; BOOST_FOREACH(const IfcRepresentationItem& item, repr->Items) { @@ -595,7 +582,6 @@ void ProcessProductRepresentation(const IfcProduct& el, aiNode* nd, std::vector< break; } } - AssignAddedMeshes(meshes,nd,conv); } diff --git a/code/IFCOpenings.cpp b/code/IFCOpenings.cpp index 7f18e1440..c26574cc3 100644 --- a/code/IFCOpenings.cpp +++ b/code/IFCOpenings.cpp @@ -1063,7 +1063,7 @@ IfcMatrix4 ProjectOntoPlane(std::vector& out_contour, const TempMesh if(!ok) { return IfcMatrix4(); } -#ifdef _DEBUG +#ifdef ASSIMP_BUILD_DEBUG const IfcFloat det = m.Determinant(); ai_assert(fabs(det-1) < 1e-5); #endif @@ -1119,7 +1119,7 @@ IfcMatrix4 ProjectOntoPlane(std::vector& out_contour, const TempMesh m = mult * m; // debug code to verify correctness -#ifdef _DEBUG +#ifdef ASSIMP_BUILD_DEBUG std::vector out_contour2; BOOST_FOREACH(const IfcVector3& x, in_verts) { const IfcVector3& vv = m * x; diff --git a/code/IFCUtil.cpp b/code/IFCUtil.cpp index 483410ff3..86ff27ddd 100644 --- a/code/IFCUtil.cpp +++ b/code/IFCUtil.cpp @@ -193,7 +193,7 @@ void TempMesh::ComputePolygonNormals(std::vector& normals, temp[cnt++] = v.x; temp[cnt++] = v.y; temp[cnt++] = v.z; -#ifdef _DEBUG +#ifdef ASSIMP_BUILD_DEBUG temp[cnt] = std::numeric_limits::quiet_NaN(); #endif ++cnt; diff --git a/code/IFCUtil.h b/code/IFCUtil.h index 7c2e0de77..f233d4256 100644 --- a/code/IFCUtil.h +++ b/code/IFCUtil.h @@ -365,7 +365,7 @@ public: // and append the result to the mesh virtual void SampleDiscrete(TempMesh& out,IfcFloat start,IfcFloat end) const; -#ifdef _DEBUG +#ifdef ASSIMP_BUILD_DEBUG // check if a particular parameter value lies within the well-defined range bool InRange(IfcFloat) const; #endif diff --git a/code/Importer.cpp b/code/Importer.cpp index 445e16be4..c6b9daf67 100644 --- a/code/Importer.cpp +++ b/code/Importer.cpp @@ -197,6 +197,7 @@ Importer::Importer(const Importer &other) pimpl->mIntProperties = other.pimpl->mIntProperties; pimpl->mFloatProperties = other.pimpl->mFloatProperties; pimpl->mStringProperties = other.pimpl->mStringProperties; + pimpl->mMatrixProperties = other.pimpl->mMatrixProperties; } // ------------------------------------------------------------------------------------------------ @@ -232,7 +233,7 @@ aiReturn Importer::RegisterLoader(BaseImporter* pImp) for(std::set::const_iterator it = st.begin(); it != st.end(); ++it) { -#ifdef _DEBUG +#ifdef ASSIMP_BUILD_DEBUG if (IsExtensionSupported(*it)) { DefaultLogger::get()->warn("The file extension " + *it + " is already in use"); } @@ -558,7 +559,7 @@ void WriteLogOpening(const std::string& file) << "" #endif -#ifndef NDEBUG +#ifdef ASSIMP_BUILD_DEBUG << " debug" #endif @@ -749,10 +750,10 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags) } } #endif // no validation -#ifdef _DEBUG +#ifdef ASSIMP_BUILD_DEBUG if (pimpl->bExtraVerbose) { -#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS +#ifdef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS DefaultLogger::get()->error("Verbose Import is not available due to build settings"); #endif // no validation pFlags |= aiProcess_ValidateDataStructure; @@ -783,9 +784,9 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags) if( !pimpl->mScene) { break; } -#ifdef _DEBUG +#ifdef ASSIMP_BUILD_DEBUG -#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS +#ifdef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS continue; #endif // no validation @@ -937,6 +938,16 @@ void Importer::SetPropertyString(const char* szName, const std::string& value, ASSIMP_END_EXCEPTION_REGION(void); } +// ------------------------------------------------------------------------------------------------ +// Set a configuration property +void Importer::SetPropertyMatrix(const char* szName, const aiMatrix4x4& value, + bool* bWasExisting /*= NULL*/) +{ + ASSIMP_BEGIN_EXCEPTION_REGION(); + SetGenericProperty(pimpl->mMatrixProperties, szName,value,bWasExisting); + ASSIMP_END_EXCEPTION_REGION(void); +} + // ------------------------------------------------------------------------------------------------ // Get a configuration property int Importer::GetPropertyInteger(const char* szName, @@ -955,12 +966,20 @@ float Importer::GetPropertyFloat(const char* szName, // ------------------------------------------------------------------------------------------------ // Get a configuration property -const std::string& Importer::GetPropertyString(const char* szName, +const std::string Importer::GetPropertyString(const char* szName, const std::string& iErrorReturn /*= ""*/) const { return GetGenericProperty(pimpl->mStringProperties,szName,iErrorReturn); } +// ------------------------------------------------------------------------------------------------ +// Get a configuration property +const aiMatrix4x4 Importer::GetPropertyMatrix(const char* szName, + const aiMatrix4x4& iErrorReturn /*= aiMatrix4x4()*/) const +{ + return GetGenericProperty(pimpl->mMatrixProperties,szName,iErrorReturn); +} + // ------------------------------------------------------------------------------------------------ // Get the memory requirements of a single node inline void AddNodeWeight(unsigned int& iScene,const aiNode* pcNode) diff --git a/code/Importer.h b/code/Importer.h index f4733c141..c61d32456 100644 --- a/code/Importer.h +++ b/code/Importer.h @@ -63,11 +63,12 @@ public: // Data type to store the key hash typedef unsigned int KeyType; - // typedefs for our three configuration maps. + // typedefs for our four configuration maps. // We don't need more, so there is no need for a generic solution typedef std::map IntPropertyMap; typedef std::map FloatPropertyMap; typedef std::map StringPropertyMap; + typedef std::map MatrixPropertyMap; public: @@ -100,6 +101,9 @@ public: /** List of string properties */ StringPropertyMap mStringProperties; + /** List of Matrix properties */ + MatrixPropertyMap mMatrixProperties; + /** Used for testing - extra verbose mode causes the ValidateDataStructure-Step * to be executed before and after every single postprocess step */ bool bExtraVerbose; @@ -135,14 +139,15 @@ public: ImporterPimpl::IntPropertyMap ints; ImporterPimpl::FloatPropertyMap floats; ImporterPimpl::StringPropertyMap strings; + ImporterPimpl::MatrixPropertyMap matrices; bool operator == (const PropertyMap& prop) const { // fixme: really isocpp? gcc complains - return ints == prop.ints && floats == prop.floats && strings == prop.strings; + return ints == prop.ints && floats == prop.floats && strings == prop.strings && matrices == prop.matrices; } bool empty () const { - return ints.empty() && floats.empty() && strings.empty(); + return ints.empty() && floats.empty() && strings.empty() && matrices.empty(); } }; //! @endcond diff --git a/code/LWOLoader.cpp b/code/LWOLoader.cpp index 0d03575ae..489ce1345 100644 --- a/code/LWOLoader.cpp +++ b/code/LWOLoader.cpp @@ -294,7 +294,7 @@ void LWOImporter::InternReadFile( const std::string& pFile, unsigned int vUVChannelIndices[AI_MAX_NUMBER_OF_TEXTURECOORDS]; unsigned int vVColorIndices[AI_MAX_NUMBER_OF_COLOR_SETS]; -#if _DEBUG +#ifdef ASSIMP_BUILD_DEBUG for (unsigned int mui = 0; mui < AI_MAX_NUMBER_OF_TEXTURECOORDS;++mui ) { vUVChannelIndices[mui] = UINT_MAX; } diff --git a/code/LineSplitter.h b/code/LineSplitter.h index cd70f882b..e51e51528 100644 --- a/code/LineSplitter.h +++ b/code/LineSplitter.h @@ -1,242 +1,238 @@ -/* -Open Asset Import Library (assimp) ----------------------------------------------------------------------- +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2012, assimp 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 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 LineSplitter.h + * @brief LineSplitter, a helper class to iterate through all lines + * of a file easily. Works with StreamReader. + */ +#ifndef INCLUDED_LINE_SPLITTER_H +#define INCLUDED_LINE_SPLITTER_H + +#include + +#include "StreamReader.h" +#include "ParsingUtils.h" + +namespace Assimp { + +// ------------------------------------------------------------------------------------------------ +/** Usage: +@code +for(LineSplitter splitter(stream);splitter;++splitter) { + + if (*splitter == "hi!") { + ... + } + else if (splitter->substr(0,5) == "hello") { + ... + // access the third token in the line (tokens are space-separated) + if (strtol(splitter[2]) > 5) { .. } + } + + std::cout << "Current line is: " << splitter.get_index() << std::endl; +} +@endcode */ +// ------------------------------------------------------------------------------------------------ +class LineSplitter +{ +public: + + typedef size_t line_idx; + +public: + + // ----------------------------------------- + /** construct from existing stream reader + note: trim is *always* assumed true if skyp_empty_lines==true + */ + LineSplitter(StreamReaderLE& stream, bool skip_empty_lines = true, bool trim = true) + : stream(stream) + , swallow() + , skip_empty_lines(skip_empty_lines) + , trim(trim) + { + cur.reserve(1024); + operator++(); + + idx = 0; + } + +public: + + // ----------------------------------------- + /** pseudo-iterator increment */ + LineSplitter& operator++() { + if(swallow) { + swallow = false; + return *this; + } + if (!*this) { + throw std::logic_error("End of file, no more lines to be retrieved."); + } + char s; + cur.clear(); + while(stream.GetRemainingSize() && (s = stream.GetI1(),1)) { + if (s == '\n' || s == '\r') { + if (skip_empty_lines) { + while (stream.GetRemainingSize() && ((s = stream.GetI1()) == ' ' || s == '\r' || s == '\n')); + if (stream.GetRemainingSize()) { + stream.IncPtr(-1); + } + } + else { + // skip both potential line terminators but don't read past this line. + if (stream.GetRemainingSize() && (s == '\r' && stream.GetI1() != '\n')) { + stream.IncPtr(-1); + } + if (trim) { + while (stream.GetRemainingSize() && ((s = stream.GetI1()) == ' ' || s == '\t')); + if (stream.GetRemainingSize()) { + stream.IncPtr(-1); + } + } + } + break; + } + cur += s; + } + ++idx; + return *this; + } + + // ----------------------------------------- + LineSplitter& operator++(int) { + return ++(*this); + } + + // ----------------------------------------- + /** get a pointer to the beginning of a particular token */ + const char* operator[] (size_t idx) const { + const char* s = operator->()->c_str(); -Copyright (c) 2006-2012, assimp team -All rights reserved. + SkipSpaces(&s); + for(size_t i = 0; i < idx; ++i) { -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 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 LineSplitter.h - * @brief LineSplitter, a helper class to iterate through all lines - * of a file easily. Works with StreamReader. - */ -#ifndef INCLUDED_LINE_SPLITTER_H -#define INCLUDED_LINE_SPLITTER_H - -#include - -#include "StreamReader.h" -#include "ParsingUtils.h" - -namespace Assimp { - -// ------------------------------------------------------------------------------------------------ -/** Usage: -@code -for(LineSplitter splitter(stream);splitter;++splitter) { - - if (*splitter == "hi!") { - ... - } - else if (splitter->substr(0,5) == "hello") { - ... - // access the third token in the line (tokens are space-separated) - if (strtol(splitter[2]) > 5) { .. } - } - - std::cout << "Current line is: " << splitter.get_index() << std::endl; -} -@endcode */ -// ------------------------------------------------------------------------------------------------ -class LineSplitter -{ -public: - - typedef size_t line_idx; - -public: - - // ----------------------------------------- - /** construct from existing stream reader - note: trim is *always* assumed true if skyp_empty_lines==true - */ - LineSplitter(StreamReaderLE& stream, bool skip_empty_lines = true, bool trim = true) - : stream(stream) - , swallow() - , skip_empty_lines(skip_empty_lines) - , trim(trim) - { - cur.reserve(1024); - operator++(); - - idx = 0; - } - -public: - - // ----------------------------------------- - /** pseudo-iterator increment */ - LineSplitter& operator++() { - if(swallow) { - swallow = false; - return *this; - } - - if (!*this) { - throw std::logic_error("End of file, no more lines to be retrieved."); - } - - char s; - - cur.clear(); - while(stream.GetRemainingSize() && (s = stream.GetI1(),1)) { - if (s == '\n' || s == '\r') { - if (skip_empty_lines) { - while (stream.GetRemainingSize() && ((s = stream.GetI1()) == ' ' || s == '\r' || s == '\n')); - if (stream.GetRemainingSize()) { - stream.IncPtr(-1); - } - } - else { - // skip both potential line terminators but don't read past this line. - if (stream.GetRemainingSize() && (s == '\r' && stream.GetI1() != '\n')) { - stream.IncPtr(-1); - } - - if (trim) { - while (stream.GetRemainingSize() && ((s = stream.GetI1()) == ' ' || s == '\t')); - if (stream.GetRemainingSize()) { - stream.IncPtr(-1); - } - } - } - - break; - } - cur += s; - } - - ++idx; - return *this; - } - - // ----------------------------------------- - LineSplitter& operator++(int) { - return ++(*this); - } - - // ----------------------------------------- - /** get a pointer to the beginning of a particular token */ - const char* operator[] (size_t idx) const { - const char* s = operator->()->c_str(); - - SkipSpaces(&s); - for(size_t i = 0; i < idx; ++i) { - - for(;!IsSpace(*s); ++s) { - if(IsLineEnd(*s)) { - throw std::range_error("Token index out of range, EOL reached"); - } - } - SkipSpaces(&s); - } - return s; - } - - // ----------------------------------------- - /** extract the start positions of N tokens from the current line*/ - template - void get_tokens(const char* (&tokens)[N]) const { - const char* s = operator->()->c_str(); - - SkipSpaces(&s); - for(size_t i = 0; i < N; ++i) { - if(IsLineEnd(*s)) { - throw std::range_error("Token count out of range, EOL reached"); - } - tokens[i] = s; - - for(;*s && !IsSpace(*s); ++s); - SkipSpaces(&s); - } - } - - // ----------------------------------------- - /** member access */ - const std::string* operator -> () const { - return &cur; - } - - std::string operator* () const { - return cur; - } - - // ----------------------------------------- - /** boolean context */ - operator bool() const { - return stream.GetRemainingSize()>0; - } - - // ----------------------------------------- - /** line indices are zero-based, empty lines are included */ - operator line_idx() const { - return idx; - } - - line_idx get_index() const { - return idx; - } - - // ----------------------------------------- - /** access the underlying stream object */ - StreamReaderLE& get_stream() { - return stream; - } - - // ----------------------------------------- - /** !strcmp((*this)->substr(0,strlen(check)),check) */ - bool match_start(const char* check) { - const size_t len = strlen(check); - - return len <= cur.length() && std::equal(check,check+len,cur.begin()); - } - - - // ----------------------------------------- - /** swallow the next call to ++, return the previous value. */ - void swallow_next_increment() { - swallow = true; - } - -private: - - line_idx idx; - std::string cur; - StreamReaderLE& stream; - bool swallow, skip_empty_lines, trim; -}; - -} -#endif // INCLUDED_LINE_SPLITTER_H + for(;!IsSpace(*s); ++s) { + if(IsLineEnd(*s)) { + throw std::range_error("Token index out of range, EOL reached"); + } + } + SkipSpaces(&s); + } + return s; + } + + // ----------------------------------------- + /** extract the start positions of N tokens from the current line*/ + template + void get_tokens(const char* (&tokens)[N]) const { + const char* s = operator->()->c_str(); + + SkipSpaces(&s); + for(size_t i = 0; i < N; ++i) { + if(IsLineEnd(*s)) { + + throw std::range_error("Token count out of range, EOL reached"); + + } + tokens[i] = s; + + for(;*s && !IsSpace(*s); ++s); + SkipSpaces(&s); + } + } + + // ----------------------------------------- + /** member access */ + const std::string* operator -> () const { + return &cur; + } + + std::string operator* () const { + return cur; + } + + // ----------------------------------------- + /** boolean context */ + operator bool() const { + return stream.GetRemainingSize()>0; + } + + // ----------------------------------------- + /** line indices are zero-based, empty lines are included */ + operator line_idx() const { + return idx; + } + + line_idx get_index() const { + return idx; + } + + // ----------------------------------------- + /** access the underlying stream object */ + StreamReaderLE& get_stream() { + return stream; + } + + // ----------------------------------------- + /** !strcmp((*this)->substr(0,strlen(check)),check) */ + bool match_start(const char* check) { + const size_t len = strlen(check); + + return len <= cur.length() && std::equal(check,check+len,cur.begin()); + } + + + // ----------------------------------------- + /** swallow the next call to ++, return the previous value. */ + void swallow_next_increment() { + swallow = true; + } + +private: + + line_idx idx; + std::string cur; + StreamReaderLE& stream; + bool swallow, skip_empty_lines, trim; +}; + +} +#endif // INCLUDED_LINE_SPLITTER_H diff --git a/code/MaterialSystem.cpp b/code/MaterialSystem.cpp index 50c403fe1..1921c7f78 100644 --- a/code/MaterialSystem.cpp +++ b/code/MaterialSystem.cpp @@ -247,6 +247,18 @@ aiReturn aiGetMaterialColor(const aiMaterial* pMat, return eRet; } +// ------------------------------------------------------------------------------------------------ +// Get a aiUVTransform (4 floats) from the material +aiReturn aiGetMaterialUVTransform(const aiMaterial* pMat, + const char* pKey, + unsigned int type, + unsigned int index, + aiUVTransform* pOut) +{ + unsigned int iMax = 4; + return aiGetMaterialFloatArray(pMat,pKey,type,index,(float*)pOut,&iMax); +} + // ------------------------------------------------------------------------------------------------ // Get a string from the material aiReturn aiGetMaterialString(const aiMaterial* pMat, diff --git a/code/ParsingUtils.h b/code/ParsingUtils.h index 5f2746455..422471fc8 100644 --- a/code/ParsingUtils.h +++ b/code/ParsingUtils.h @@ -115,7 +115,7 @@ AI_FORCE_INLINE bool SkipSpaces( const char_t** inout) } // --------------------------------------------------------------------------------- template -inline bool SkipLine( const char_t* in, const char_t** out) +AI_FORCE_INLINE bool SkipLine( const char_t* in, const char_t** out) { while (*in != (char_t)'\r' && *in != (char_t)'\n' && *in != (char_t)'\0')in++; @@ -126,13 +126,13 @@ inline bool SkipLine( const char_t* in, const char_t** out) } // --------------------------------------------------------------------------------- template -inline bool SkipLine( const char_t** inout) +AI_FORCE_INLINE bool SkipLine( const char_t** inout) { return SkipLine(*inout,inout); } // --------------------------------------------------------------------------------- template -inline bool SkipSpacesAndLineEnd( const char_t* in, const char_t** out) +AI_FORCE_INLINE bool SkipSpacesAndLineEnd( const char_t* in, const char_t** out) { while (*in == (char_t)' ' || *in == (char_t)'\t' || *in == (char_t)'\r' || *in == (char_t)'\n')in++; @@ -141,13 +141,13 @@ inline bool SkipSpacesAndLineEnd( const char_t* in, const char_t** out) } // --------------------------------------------------------------------------------- template -inline bool SkipSpacesAndLineEnd( const char_t** inout) +AI_FORCE_INLINE bool SkipSpacesAndLineEnd( const char_t** inout) { return SkipSpacesAndLineEnd(*inout,inout); } // --------------------------------------------------------------------------------- template -inline bool GetNextLine(const char_t*& buffer, char_t out[4096]) +AI_FORCE_INLINE bool GetNextLine(const char_t*& buffer, char_t out[4096]) { if ((char_t)'\0' == *buffer)return false; diff --git a/code/PostStepRegistry.cpp b/code/PostStepRegistry.cpp index b6ad6157d..5593a7f41 100644 --- a/code/PostStepRegistry.cpp +++ b/code/PostStepRegistry.cpp @@ -133,6 +133,15 @@ void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out) // validated - as RegisterPPStep() does - all dependencies must be given. // ---------------------------------------------------------------------------- out.reserve(25); +#if (!defined ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS) + out.push_back( new MakeLeftHandedProcess()); +#endif +#if (!defined ASSIMP_BUILD_NO_FLIPUVS_PROCESS) + out.push_back( new FlipUVsProcess()); +#endif +#if (!defined ASSIMP_BUILD_NO_FLIPWINDINGORDER_PROCESS) + out.push_back( new FlipWindingOrderProcess()); +#endif #if (!defined ASSIMP_BUILD_NO_REMOVEVC_PROCESS) out.push_back( new RemoveVCProcess()); #endif @@ -207,15 +216,6 @@ void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out) #if (!defined ASSIMP_BUILD_NO_SPLITLARGEMESHES_PROCESS) out.push_back( new SplitLargeMeshesProcess_Vertex()); #endif -#if (!defined ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS) - out.push_back( new MakeLeftHandedProcess()); -#endif -#if (!defined ASSIMP_BUILD_NO_FLIPUVS_PROCESS) - out.push_back( new FlipUVsProcess()); -#endif -#if (!defined ASSIMP_BUILD_NO_FLIPWINDINGORDER_PROCESS) - out.push_back( new FlipWindingOrderProcess()); -#endif #if (!defined ASSIMP_BUILD_NO_DEBONE_PROCESS) out.push_back( new DeboneProcess()); #endif diff --git a/code/PretransformVertices.cpp b/code/PretransformVertices.cpp index cfaa2c24f..007897c93 100644 --- a/code/PretransformVertices.cpp +++ b/code/PretransformVertices.cpp @@ -57,7 +57,7 @@ using namespace Assimp; // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer PretransformVertices::PretransformVertices() -: configKeepHierarchy (false) +: configKeepHierarchy (false), configNormalize(false), configTransform(false), configTransformation() { } @@ -79,9 +79,13 @@ bool PretransformVertices::IsActive( unsigned int pFlags) const // Setup import configuration void PretransformVertices::SetupProperties(const Importer* pImp) { - // Get the current value of AI_CONFIG_PP_PTV_KEEP_HIERARCHY and AI_CONFIG_PP_PTV_NORMALIZE + // Get the current value of AI_CONFIG_PP_PTV_KEEP_HIERARCHY, AI_CONFIG_PP_PTV_NORMALIZE, + // AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION and AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION configKeepHierarchy = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_KEEP_HIERARCHY,0)); configNormalize = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_NORMALIZE,0)); + configTransform = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION,0)); + + configTransformation = pImp->GetPropertyMatrix(AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION, aiMatrix4x4()); } // ------------------------------------------------------------------------------------------------ @@ -391,6 +395,8 @@ void PretransformVertices::BuildWCSMeshes(std::vector& out, aiMesh** in ntz->mBones = reinterpret_cast (&node->mTransformation); out.push_back(ntz); + + node->mMeshes[i] = numIn + out.size() - 1; } } } @@ -437,6 +443,10 @@ void PretransformVertices::Execute( aiScene* pScene) const unsigned int iOldAnimationChannels = pScene->mNumAnimations; const unsigned int iOldNodes = CountNodes(pScene->mRootNode); + if(configTransform) { + pScene->mRootNode->mTransformation = configTransformation; + } + // first compute absolute transformation matrices for all nodes ComputeAbsoluteTransform(pScene->mRootNode); diff --git a/code/PretransformVertices.h b/code/PretransformVertices.h index bfe2c84c8..b1b42c00e 100644 --- a/code/PretransformVertices.h +++ b/code/PretransformVertices.h @@ -152,8 +152,10 @@ private: //! Configuration option: keep scene hierarchy as long as possible - bool configKeepHierarchy, configNormalize; - + bool configKeepHierarchy; + bool configNormalize; + bool configTransform; + aiMatrix4x4 configTransformation; }; } // end of namespace Assimp diff --git a/code/Q3BSPFileImporter.cpp b/code/Q3BSPFileImporter.cpp index 721dda174..ecb28e06e 100644 --- a/code/Q3BSPFileImporter.cpp +++ b/code/Q3BSPFileImporter.cpp @@ -185,9 +185,9 @@ const aiImporterDesc* Q3BSPFileImporter::GetInfo () const // ------------------------------------------------------------------------------------------------ // Import method. -void Q3BSPFileImporter::InternReadFile(const std::string &rFile, aiScene* pScene, IOSystem* /*pIOHandler*/) +void Q3BSPFileImporter::InternReadFile(const std::string &rFile, aiScene* pScene, IOSystem* pIOHandler) { - Q3BSPZipArchive Archive( rFile ); + Q3BSPZipArchive Archive( pIOHandler, rFile ); if ( !Archive.isOpen() ) { throw DeadlyImportError( "Failed to open file " + rFile + "." ); diff --git a/code/Q3BSPZipArchive.cpp b/code/Q3BSPZipArchive.cpp index e01ed3fec..947b7ca7b 100644 --- a/code/Q3BSPZipArchive.cpp +++ b/code/Q3BSPZipArchive.cpp @@ -46,23 +46,144 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -namespace Assimp -{ -namespace Q3BSP -{ +namespace Assimp { +namespace Q3BSP { + +voidpf IOSystem2Unzip::open(voidpf opaque, const char* filename, int mode) { + IOSystem* io_system = (IOSystem*) opaque; + + const char* mode_fopen = NULL; + if((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) { + mode_fopen = "rb"; + } else { + if(mode & ZLIB_FILEFUNC_MODE_EXISTING) { + mode_fopen = "r+b"; + } else { + if(mode & ZLIB_FILEFUNC_MODE_CREATE) { + mode_fopen = "wb"; + } + } + } + + return (voidpf) io_system->Open(filename, mode_fopen); +} + +uLong IOSystem2Unzip::read(voidpf opaque, voidpf stream, void* buf, uLong size) { + IOStream* io_stream = (IOStream*) stream; + + return io_stream->Read(buf, 1, size); +} + +uLong IOSystem2Unzip::write(voidpf opaque, voidpf stream, const void* buf, uLong size) { + IOStream* io_stream = (IOStream*) stream; + + return io_stream->Write(buf, 1, size); +} + +long IOSystem2Unzip::tell(voidpf opaque, voidpf stream) { + IOStream* io_stream = (IOStream*) stream; + + return io_stream->Tell(); +} + +long IOSystem2Unzip::seek(voidpf opaque, voidpf stream, uLong offset, int origin) { + IOStream* io_stream = (IOStream*) stream; + + aiOrigin assimp_origin; + switch (origin) { + default: + case ZLIB_FILEFUNC_SEEK_CUR: + assimp_origin = aiOrigin_CUR; + break; + case ZLIB_FILEFUNC_SEEK_END: + assimp_origin = aiOrigin_END; + break; + case ZLIB_FILEFUNC_SEEK_SET: + assimp_origin = aiOrigin_SET; + break; + } + + return (io_stream->Seek(offset, assimp_origin) == aiReturn_SUCCESS ? 0 : -1); +} + +int IOSystem2Unzip::close(voidpf opaque, voidpf stream) { + IOSystem* io_system = (IOSystem*) opaque; + IOStream* io_stream = (IOStream*) stream; + + io_system->Close(io_stream); + + return 0; +} + +int IOSystem2Unzip::testerror(voidpf opaque, voidpf stream) { + return 0; +} + +zlib_filefunc_def IOSystem2Unzip::get(IOSystem* pIOHandler) { + zlib_filefunc_def mapping; + + mapping.zopen_file = open; + mapping.zread_file = read; + mapping.zwrite_file = write; + mapping.ztell_file = tell; + mapping.zseek_file = seek; + mapping.zclose_file = close; + mapping.zerror_file = testerror; + mapping.opaque = (voidpf) pIOHandler; + + return mapping; +} + +// ------------------------------------------------------------------------------------------------ +ZipFile::ZipFile(size_t size) : m_Size(size) { + ai_assert(m_Size != 0); + + m_Buffer = std::malloc(m_Size); +} + +ZipFile::~ZipFile() { + std::free(m_Buffer); + m_Buffer = NULL; +} + +size_t ZipFile::Read(void* pvBuffer, size_t pSize, size_t pCount) { + const size_t size = pSize * pCount; + assert(size <= m_Size); + + std::memcpy(pvBuffer, m_Buffer, size); + + return size; +} + +size_t ZipFile::Write(const void* /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) { + return 0; +} + +size_t ZipFile::FileSize() const { + return m_Size; +} + +aiReturn ZipFile::Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/) { + return aiReturn_FAILURE; +} + +size_t ZipFile::Tell() const { + return 0; +} + +void ZipFile::Flush() { + // empty +} // ------------------------------------------------------------------------------------------------ // Constructor. -Q3BSPZipArchive::Q3BSPZipArchive( const std::string& rFile ) : - m_ZipFileHandle( NULL ), - m_FileList(), - m_bDirty( true ) -{ - if ( !rFile.empty() ) - { - m_ZipFileHandle = unzOpen( rFile.c_str() ); - if ( NULL != m_ZipFileHandle ) - { +Q3BSPZipArchive::Q3BSPZipArchive(IOSystem* pIOHandler, const std::string& rFile) : m_ZipFileHandle(NULL), m_ArchiveMap() { + if (! rFile.empty()) { + zlib_filefunc_def mapping = IOSystem2Unzip::get(pIOHandler); + + m_ZipFileHandle = unzOpen2(rFile.c_str(), &mapping); + + if(m_ZipFileHandle != NULL) { mapArchive(); } } @@ -70,127 +191,122 @@ Q3BSPZipArchive::Q3BSPZipArchive( const std::string& rFile ) : // ------------------------------------------------------------------------------------------------ // Destructor. -Q3BSPZipArchive::~Q3BSPZipArchive() -{ - if ( NULL != m_ZipFileHandle ) - { - unzClose( m_ZipFileHandle ); +Q3BSPZipArchive::~Q3BSPZipArchive() { + for( std::map::iterator it(m_ArchiveMap.begin()), end(m_ArchiveMap.end()); it != end; ++it ) { + delete it->second; + } + m_ArchiveMap.clear(); + + if(m_ZipFileHandle != NULL) { + unzClose(m_ZipFileHandle); + m_ZipFileHandle = NULL; } - m_ZipFileHandle = NULL; - m_FileList.clear(); } // ------------------------------------------------------------------------------------------------ // Returns true, if the archive is already open. -bool Q3BSPZipArchive::isOpen() const -{ - return ( NULL != m_ZipFileHandle ); +bool Q3BSPZipArchive::isOpen() const { + return (m_ZipFileHandle != NULL); } // ------------------------------------------------------------------------------------------------ // Returns true, if the filename is part of the archive. -bool Q3BSPZipArchive::Exists( const char* pFile ) const -{ - ai_assert( NULL != pFile ); - if ( NULL == pFile ) - { - return false; +bool Q3BSPZipArchive::Exists(const char* pFile) const { + ai_assert(pFile != NULL); + + bool exist = false; + + if (pFile != NULL) { + std::string rFile(pFile); + std::map::const_iterator it = m_ArchiveMap.find(rFile); + + if(it != m_ArchiveMap.end()) { + exist = true; + } } - std::string rFile( pFile ); - std::vector::const_iterator it = std::find( m_FileList.begin(), m_FileList.end(), rFile ); - if ( m_FileList.end() == it ) - { - return false; - } - - return true; + return exist; } // ------------------------------------------------------------------------------------------------ // Returns the separator delimiter. -char Q3BSPZipArchive::getOsSeparator() const -{ +char Q3BSPZipArchive::getOsSeparator() const { +#ifndef _WIN32 return '/'; +#else + return '\\'; +#endif } // ------------------------------------------------------------------------------------------------ // Opens a file, which is part of the archive. -IOStream *Q3BSPZipArchive::Open( const char* pFile, const char* /*pMode*/ ) -{ - ai_assert( NULL != pFile ); +IOStream *Q3BSPZipArchive::Open(const char* pFile, const char* /*pMode*/) { + ai_assert(pFile != NULL); - std::string rItem( pFile ); - std::vector::iterator it = std::find( m_FileList.begin(), m_FileList.end(), rItem ); - if ( m_FileList.end() == it ) - return NULL; + IOStream* result = NULL; - ZipFile *pZipFile = new ZipFile( *it, m_ZipFileHandle ); - m_ArchiveMap[ rItem ] = pZipFile; + std::map::iterator it = m_ArchiveMap.find(pFile); - return pZipFile; + if(it != m_ArchiveMap.end()) { + result = (IOStream*) it->second; + } + + return result; } // ------------------------------------------------------------------------------------------------ // Close a filestream. -void Q3BSPZipArchive::Close( IOStream *pFile ) -{ - ai_assert( NULL != pFile ); +void Q3BSPZipArchive::Close(IOStream *pFile) { + ai_assert(pFile != NULL); - std::map::iterator it; - for ( it = m_ArchiveMap.begin(); it != m_ArchiveMap.end(); ++it ) - { - if ( (*it).second == pFile ) - { - ZipFile *pZipFile = reinterpret_cast( (*it).second ); - delete pZipFile; - m_ArchiveMap.erase( it ); - break; - } - } + // We don't do anything in case the file would be opened again in the future } // ------------------------------------------------------------------------------------------------ // Returns the file-list of the archive. -void Q3BSPZipArchive::getFileList( std::vector &rFileList ) -{ - rFileList = m_FileList; +void Q3BSPZipArchive::getFileList(std::vector &rFileList) { + rFileList.clear(); + + for(std::map::iterator it(m_ArchiveMap.begin()), end(m_ArchiveMap.end()); it != end; ++it) { + rFileList.push_back(it->first); + } } // ------------------------------------------------------------------------------------------------ // Maps the archive content. -bool Q3BSPZipArchive::mapArchive() -{ - if ( NULL == m_ZipFileHandle ) - return false; +bool Q3BSPZipArchive::mapArchive() { + bool success = false; - if ( !m_bDirty ) - return true; + if(m_ZipFileHandle != NULL) { + if(m_ArchiveMap.empty()) { + // At first ensure file is already open + if(unzGoToFirstFile(m_ZipFileHandle) == UNZ_OK) { + // Loop over all files + do { + char filename[FileNameSize]; + unz_file_info fileInfo; - if ( !m_FileList.empty() ) - m_FileList.resize( 0 ); + if(unzGetCurrentFileInfo(m_ZipFileHandle, &fileInfo, filename, FileNameSize, NULL, 0, NULL, 0) == UNZ_OK) { + // The file has EXACTLY the size of uncompressed_size. In C + // you need to mark the last character with '\0', so add + // another character + if(unzOpenCurrentFile(m_ZipFileHandle) == UNZ_OK) { + std::pair::iterator, bool> result = m_ArchiveMap.insert(std::make_pair(filename, new ZipFile(fileInfo.uncompressed_size))); - // At first ensure file is already open - if ( UNZ_OK == unzGoToFirstFile( m_ZipFileHandle ) ) - { - char filename[ FileNameSize ]; - unzGetCurrentFileInfo( m_ZipFileHandle, NULL, filename, FileNameSize, NULL, 0, NULL, 0 ); - m_FileList.push_back( filename ); - unzCloseCurrentFile( m_ZipFileHandle ); - - // Loop over all files - while ( unzGoToNextFile( m_ZipFileHandle ) != UNZ_END_OF_LIST_OF_FILE ) - { - char filename[ FileNameSize ]; - unzGetCurrentFileInfo( m_ZipFileHandle, NULL, filename, FileNameSize, NULL, 0, NULL, 0 ); - m_FileList.push_back( filename ); - unzCloseCurrentFile( m_ZipFileHandle ); + if(unzReadCurrentFile(m_ZipFileHandle, result.first->second->m_Buffer, fileInfo.uncompressed_size) == (long int) fileInfo.uncompressed_size) { + if(unzCloseCurrentFile(m_ZipFileHandle) == UNZ_OK) { + // Nothing to do anymore... + } + } + } + } + } while(unzGoToNextFile(m_ZipFileHandle) != UNZ_END_OF_LIST_OF_FILE); + } } - } - - std::sort( m_FileList.begin(), m_FileList.end() ); - m_bDirty = false; - return true; + success = true; + } + + return success; } // ------------------------------------------------------------------------------------------------ diff --git a/code/Q3BSPZipArchive.h b/code/Q3BSPZipArchive.h index 06d8370e3..3050d10d4 100644 --- a/code/Q3BSPZipArchive.h +++ b/code/Q3BSPZipArchive.h @@ -48,10 +48,35 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -namespace Assimp -{ -namespace Q3BSP -{ +namespace Assimp { +namespace Q3BSP { + +// ------------------------------------------------------------------------------------------------ +/// \class IOSystem2Unzip +/// \ingroup Assimp::Q3BSP +/// +/// \brief +// ------------------------------------------------------------------------------------------------ +class IOSystem2Unzip { + + public: + + static voidpf open(voidpf opaque, const char* filename, int mode); + + static uLong read(voidpf opaque, voidpf stream, void* buf, uLong size); + + static uLong write(voidpf opaque, voidpf stream, const void* buf, uLong size); + + static long tell(voidpf opaque, voidpf stream); + + static long seek(voidpf opaque, voidpf stream, uLong offset, int origin); + + static int close(voidpf opaque, voidpf stream); + + static int testerror(voidpf opaque, voidpf stream); + + static zlib_filefunc_def get(IOSystem* pIOHandler); +}; // ------------------------------------------------------------------------------------------------ /// \class ZipFile @@ -59,88 +84,33 @@ namespace Q3BSP /// /// \brief // ------------------------------------------------------------------------------------------------ -class ZipFile : public IOStream -{ -public: - ZipFile( const std::string &rFileName, unzFile zipFile ) : - m_Name( rFileName ), - m_zipFile( zipFile ) - { - ai_assert( NULL != m_zipFile ); - } +class ZipFile : public IOStream { + + friend class Q3BSPZipArchive; + + public: + + ZipFile(size_t size); - ~ZipFile() - { - m_zipFile = NULL; - } + ~ZipFile(); - size_t Read(void* pvBuffer, size_t pSize, size_t pCount ) - { - size_t bytes_read = 0; - if ( NULL == m_zipFile ) - return bytes_read; - - // search file and place file pointer there - if ( unzLocateFile( m_zipFile, m_Name.c_str(), 0 ) == UNZ_OK ) - { - // get file size, etc. - unz_file_info fileInfo; - unzGetCurrentFileInfo( m_zipFile, &fileInfo, 0, 0, 0, 0, 0, 0 ); - const size_t size = pSize * pCount; - assert( size <= fileInfo.uncompressed_size ); - - // The file has EXACTLY the size of uncompressed_size. In C - // you need to mark the last character with '\0', so add - // another character - unzOpenCurrentFile( m_zipFile ); - const int ret = unzReadCurrentFile( m_zipFile, pvBuffer, fileInfo.uncompressed_size); - size_t filesize = fileInfo.uncompressed_size; - if ( ret < 0 || size_t(ret) != filesize ) - { - return 0; - } - bytes_read = ret; - unzCloseCurrentFile( m_zipFile ); - } - return bytes_read; - } + size_t Read(void* pvBuffer, size_t pSize, size_t pCount ); - size_t Write(const void* /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) - { - return 0; - } + size_t Write(const void* /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/); - size_t FileSize() const - { - if ( NULL == m_zipFile ) - return 0; - if ( unzLocateFile( m_zipFile, m_Name.c_str(), 0 ) == UNZ_OK ) - { - unz_file_info fileInfo; - unzGetCurrentFileInfo( m_zipFile, &fileInfo, 0, 0, 0, 0, 0, 0 ); - return fileInfo.uncompressed_size; - } - return 0; - } + size_t FileSize() const; - aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/) - { - return aiReturn_FAILURE; - } + aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/); - size_t Tell() const - { - return 0; - } + size_t Tell() const; - void Flush() - { - // empty - } + void Flush(); -private: - std::string m_Name; - unzFile m_zipFile; + private: + + void* m_Buffer; + + size_t m_Size; }; // ------------------------------------------------------------------------------------------------ @@ -150,29 +120,40 @@ private: /// \brief IMplements a zip archive like the WinZip archives. Will be also used to import data /// from a P3K archive ( Quake level format ). // ------------------------------------------------------------------------------------------------ -class Q3BSPZipArchive : public Assimp::IOSystem -{ -public: - static const unsigned int FileNameSize = 256; +class Q3BSPZipArchive : public Assimp::IOSystem { -public: - Q3BSPZipArchive( const std::string & rFile ); - ~Q3BSPZipArchive(); - bool Exists( const char* pFile) const; - char getOsSeparator() const; - IOStream* Open(const char* pFile, const char* pMode = "rb"); - void Close( IOStream* pFile); - bool isOpen() const; - void getFileList( std::vector &rFileList ); + public: -private: - bool mapArchive(); + static const unsigned int FileNameSize = 256; + + public: + + Q3BSPZipArchive(IOSystem* pIOHandler, const std::string & rFile); + + ~Q3BSPZipArchive(); + + bool Exists(const char* pFile) const; + + char getOsSeparator() const; + + IOStream* Open(const char* pFile, const char* pMode = "rb"); + + void Close(IOStream* pFile); + + bool isOpen() const; + + void getFileList(std::vector &rFileList); + + private: + + bool mapArchive(); + + private: + + unzFile m_ZipFileHandle; + + std::map m_ArchiveMap; -private: - unzFile m_ZipFileHandle; - std::map m_ArchiveMap; - std::vector m_FileList; - bool m_bDirty; }; // ------------------------------------------------------------------------------------------------ diff --git a/code/RemoveRedundantMaterials.cpp b/code/RemoveRedundantMaterials.cpp index 398fea4b0..2285d06b4 100644 --- a/code/RemoveRedundantMaterials.cpp +++ b/code/RemoveRedundantMaterials.cpp @@ -142,6 +142,7 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene) // if the material is not referenced ... remove it if (!abReferenced[i]) { ++unreferenced; + delete pScene->mMaterials[i]; continue; } diff --git a/code/STEPFile.h b/code/STEPFile.h index 3c63bd700..510e051ae 100644 --- a/code/STEPFile.h +++ b/code/STEPFile.h @@ -192,19 +192,19 @@ namespace STEP { } // utilities to deal with SELECT entities, which currently lack automatic - // conversion support. - template - const T& ResolveSelect(const DB& db) const { - return Couple(db).MustGetObject(To())->template To(); - } - - template - const T* ResolveSelectPtr(const DB& db) const { - const EXPRESS::ENTITY* e = ToPtr(); - return e?Couple(db).MustGetObject(*e)->template ToPtr():(const T*)0; - } - - public: + // conversion support. + template + const T& ResolveSelect(const DB& db) const { + return Couple(db).MustGetObject(To())->template To(); + } + + template + const T* ResolveSelectPtr(const DB& db) const { + const EXPRESS::ENTITY* e = ToPtr(); + return e?Couple(db).MustGetObject(*e)->template ToPtr():(const T*)0; + } + + public: /** parse a variable from a string and set 'inout' to the character * behind the last consumed character. An optional schema enables, diff --git a/code/STEPFileReader.cpp b/code/STEPFileReader.cpp index b03e53a87..96db1d433 100644 --- a/code/STEPFileReader.cpp +++ b/code/STEPFileReader.cpp @@ -175,7 +175,7 @@ bool IsEntityDef(const std::string& snext) if (*it == '=') { return true; } - if (*it < '0' || *it > '9') { + if ((*it < '0' || *it > '9') && *it != ' ') { break; } } @@ -197,16 +197,17 @@ void STEP::ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme, const DB::ObjectMap& map = db.GetObjects(); LineSplitter& splitter = db.GetSplitter(); + while (splitter) { bool has_next = false; std::string s = *splitter; if (s == "ENDSEC;") { break; } + s.erase(std::remove(s.begin(), s.end(), ' '), s.end()); // want one-based line numbers for human readers, so +1 const uint64_t line = splitter.get_index()+1; - // LineSplitter already ignores empty lines ai_assert(s.length()); if (s[0] != '#') { @@ -214,12 +215,10 @@ void STEP::ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme, ++splitter; continue; } - // --- // extract id, entity class name and argument string, // but don't create the actual object yet. // --- - const std::string::size_type n0 = s.find_first_of('='); if (n0 == std::string::npos) { DefaultLogger::get()->warn(AddLineNumber("expected token \'=\'",line)); @@ -233,13 +232,10 @@ void STEP::ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme, ++splitter; continue; } - std::string::size_type n1 = s.find_first_of('(',n0); if (n1 == std::string::npos) { - has_next = true; bool ok = false; - for( ++splitter; splitter; ++splitter) { const std::string& snext = *splitter; if (snext.empty()) { @@ -269,13 +265,11 @@ void STEP::ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme, has_next = true; bool ok = false; - for( ++splitter; splitter; ++splitter) { const std::string& snext = *splitter; if (snext.empty()) { continue; } - // the next line doesn't start an entity, so maybe it is // just a continuation for this line, keep going if (!IsEntityDef(snext)) { @@ -287,7 +281,6 @@ void STEP::ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme, break; } } - if(!ok) { DefaultLogger::get()->warn(AddLineNumber("expected token \')\'",line)); continue; @@ -300,24 +293,18 @@ void STEP::ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme, std::string::size_type ns = n0; do ++ns; while( IsSpace(s.at(ns))); - std::string::size_type ne = n1; do --ne; while( IsSpace(s.at(ne))); - std::string type = s.substr(ns,ne-ns+1); std::transform( type.begin(), type.end(), type.begin(), &Assimp::ToLower ); - const char* sz = scheme.GetStaticStringForToken(type); if(sz) { - const std::string::size_type len = n2-n1+1; char* const copysz = new char[len+1]; std::copy(s.c_str()+n1,s.c_str()+n2+1,copysz); copysz[len] = '\0'; - db.InternInsert(new LazyObject(db,id,line,sz,copysz)); } - if(!has_next) { ++splitter; } @@ -327,7 +314,7 @@ void STEP::ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme, DefaultLogger::get()->warn("STEP: ignoring unexpected EOF"); } - if ( !DefaultLogger::isNullLogger() ){ + if ( !DefaultLogger::isNullLogger()){ DefaultLogger::get()->debug((Formatter::format(),"STEP: got ",map.size()," object records with ", db.GetRefs().size()," inverse index entries")); } @@ -338,7 +325,6 @@ boost::shared_ptr EXPRESS::DataType::Parse(const char*& { const char* cur = inout; SkipSpaces(&cur); - if (*cur == ',' || IsSpaceOrNewLine(*cur)) { throw STEP::SyntaxError("unexpected token, expected parameter",line); } diff --git a/code/STEPFileReader.h b/code/STEPFileReader.h index 3a8f26b50..8873691d7 100644 --- a/code/STEPFileReader.h +++ b/code/STEPFileReader.h @@ -47,12 +47,10 @@ namespace Assimp { namespace STEP { // ### Parsing a STEP file is a twofold procedure ### - // -------------------------------------------------------------------------- // 1) read file header and return to caller, who checks if the // file is of a supported schema .. DB* ReadFileHeader(boost::shared_ptr stream); - // -------------------------------------------------------------------------- // 2) read the actual file contents using a user-supplied set of // conversion functions to interpret the data. @@ -60,8 +58,6 @@ namespace STEP { template inline void ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme, const char* const (&arr)[N], const char* const (&arr2)[N2]) { return ReadFile(db,scheme,arr,N,arr2,N2); } - - } // ! STEP } // ! Assimp diff --git a/code/SceneCombiner.cpp b/code/SceneCombiner.cpp index 7a732330b..d6b138d74 100644 --- a/code/SceneCombiner.cpp +++ b/code/SceneCombiner.cpp @@ -880,6 +880,59 @@ void SceneCombiner::MergeMeshes(aiMesh** _out,unsigned int /*flags*/, delete *it; } +// ------------------------------------------------------------------------------------------------ +void SceneCombiner::MergeMaterials(aiMaterial** dest, + std::vector::const_iterator begin, + std::vector::const_iterator end) +{ + ai_assert(NULL != dest); + + if (begin == end) { + *dest = NULL; // no materials ... + return; + } + + // Allocate the output material + aiMaterial* out = *dest = new aiMaterial(); + + // Get the maximal number of properties + unsigned int size = 0; + for (std::vector::const_iterator it = begin; it != end; ++it) { + size += (*it)->mNumProperties; + } + + out->Clear(); + delete[] out->mProperties; + + out->mNumAllocated = size; + out->mNumProperties = 0; + out->mProperties = new aiMaterialProperty*[out->mNumAllocated]; + + for (std::vector::const_iterator it = begin; it != end; ++it) { + for(unsigned int i = 0; i < (*it)->mNumProperties; ++i) { + aiMaterialProperty* sprop = (*it)->mProperties[i]; + + // Test if we already have a matching property + const aiMaterialProperty* prop_exist; + if(aiGetMaterialProperty(out, sprop->mKey.C_Str(), sprop->mType, sprop->mIndex, &prop_exist) != AI_SUCCESS) { + // If not, we add it to the new material + aiMaterialProperty* prop = out->mProperties[out->mNumProperties] = new aiMaterialProperty(); + + prop->mDataLength = sprop->mDataLength; + prop->mData = new char[prop->mDataLength]; + ::memcpy(prop->mData, sprop->mData, prop->mDataLength); + + prop->mIndex = sprop->mIndex; + prop->mSemantic = sprop->mSemantic; + prop->mKey = sprop->mKey; + prop->mType = sprop->mType; + + out->mNumProperties++; + } + } + } +} + // ------------------------------------------------------------------------------------------------ template inline void CopyPtrArray (Type**& dest, const Type* const * src, unsigned int num) @@ -1012,6 +1065,10 @@ void SceneCombiner::Copy (aiMaterial** _dest, const aiMaterial* src) ai_assert(NULL != _dest && NULL != src); aiMaterial* dest = (aiMaterial*) ( *_dest = new aiMaterial() ); + + dest->Clear(); + delete[] dest->mProperties; + dest->mNumAllocated = src->mNumAllocated; dest->mNumProperties = src->mNumProperties; dest->mProperties = new aiMaterialProperty* [dest->mNumAllocated]; diff --git a/code/SceneCombiner.h b/code/SceneCombiner.h index bda8f907d..e7dd242fd 100644 --- a/code/SceneCombiner.h +++ b/code/SceneCombiner.h @@ -248,6 +248,20 @@ public: static void MergeBones(aiMesh* out,std::vector::const_iterator it, std::vector::const_iterator end); + // ------------------------------------------------------------------- + /** Merges two or more materials + * + * The materials should be complementary as much as possible. In case + * of a property present in different materials, the first occurence + * is used. + * + * @param dest Destination material. Must be empty. + * @param begin First material to be processed + * @param end Points to the material after the last material to be processed + */ + static void MergeMaterials(aiMaterial** dest, + std::vector::const_iterator begin, + std::vector::const_iterator end); // ------------------------------------------------------------------- /** Builds a list of uniquely named bones in a mesh list diff --git a/code/ScenePreprocessor.cpp b/code/ScenePreprocessor.cpp index 8ab4756db..3e72ad72c 100644 --- a/code/ScenePreprocessor.cpp +++ b/code/ScenePreprocessor.cpp @@ -72,7 +72,7 @@ void ScenePreprocessor::ProcessScene () aiColor3D clr(0.6f,0.6f,0.6f); helper->AddProperty(&clr,1,AI_MATKEY_COLOR_DIFFUSE); - // setup the default name to make this material identifyable + // setup the default name to make this material identifiable name.Set(AI_DEFAULT_MATERIAL_NAME); helper->AddProperty(&name,AI_MATKEY_NAME); diff --git a/code/SmoothingGroups.h b/code/SmoothingGroups.h index 95c93c8d2..41311f73d 100644 --- a/code/SmoothingGroups.h +++ b/code/SmoothingGroups.h @@ -52,7 +52,7 @@ struct FaceWithSmoothingGroup { // let the rest uninitialized for performance - in release builds. // in debug builds set all indices to a common magic value -#ifdef _DEBUG +#ifdef ASSIMP_BUILD_DEBUG this->mIndices[0] = 0xffffffff; this->mIndices[1] = 0xffffffff; this->mIndices[2] = 0xffffffff; diff --git a/code/SpatialSort.cpp b/code/SpatialSort.cpp index a5fe87b2a..085862300 100644 --- a/code/SpatialSort.cpp +++ b/code/SpatialSort.cpp @@ -329,7 +329,7 @@ unsigned int SpatialSort::GenerateMappingTable(std::vector& fill,f ++t; } -#ifdef _DEBUG +#ifdef ASSIMP_BUILD_DEBUG // debug invariant: mPositions[i].mIndex values must range from 0 to mPositions.size()-1 for (size_t i = 0; i < fill.size(); ++i) { diff --git a/code/Subdivision.cpp b/code/Subdivision.cpp index 74b56a245..03200818c 100644 --- a/code/Subdivision.cpp +++ b/code/Subdivision.cpp @@ -383,7 +383,7 @@ void CatmullClarkSubdivider::InternSubdivide ( } // check the other way round for consistency -#ifdef _DEBUG +#ifdef ASSIMP_BUILD_DEBUG for (size_t t = 0; t < ofsadjvec.size()-1; ++t) { for (unsigned int m = 0; m < cntadjfac[t]; ++m) { @@ -530,7 +530,7 @@ void CatmullClarkSubdivider::InternSubdivide ( ai_assert(adj[o]-moffsets[nidx].first < mp->mNumFaces); const aiFace& f = mp->mFaces[adj[o]-moffsets[nidx].first]; -# ifdef _DEBUG +# ifdef ASSIMP_BUILD_DEBUG bool haveit = false; # endif @@ -553,7 +553,7 @@ void CatmullClarkSubdivider::InternSubdivide ( // fixme: replace with mod face.mNumIndices? R += c0.midpoint+c1.midpoint; -# ifdef _DEBUG +# ifdef ASSIMP_BUILD_DEBUG haveit = true; # endif break; diff --git a/code/ValidateDataStructure.cpp b/code/ValidateDataStructure.cpp index 7b61c4778..937d3830e 100644 --- a/code/ValidateDataStructure.cpp +++ b/code/ValidateDataStructure.cpp @@ -86,7 +86,7 @@ AI_WONT_RETURN void ValidateDSProcess::ReportError(const char* msg,...) ai_assert(iLen > 0); va_end(args); -#ifdef _DEBUG +#ifdef ASSIMP_BUILD_DEBUG ai_assert( false ); #endif throw DeadlyImportError("Validation failed: " + std::string(szBuffer,iLen)); diff --git a/code/fast_atof.h b/code/fast_atof.h index a10ee9666..5e6f5e4a5 100644 --- a/code/fast_atof.h +++ b/code/fast_atof.h @@ -21,23 +21,23 @@ namespace Assimp { -const float fast_atof_table[16] = { // we write [16] here instead of [] to work around a swig bug - 0.f, - 0.1f, - 0.01f, - 0.001f, - 0.0001f, - 0.00001f, - 0.000001f, - 0.0000001f, - 0.00000001f, - 0.000000001f, - 0.0000000001f, - 0.00000000001f, - 0.000000000001f, - 0.0000000000001f, - 0.00000000000001f, - 0.000000000000001f +const double fast_atof_table[16] = { // we write [16] here instead of [] to work around a swig bug + 0.0, + 0.1, + 0.01, + 0.001, + 0.0001, + 0.00001, + 0.000001, + 0.0000001, + 0.00000001, + 0.000000001, + 0.0000000001, + 0.00000000001, + 0.000000000001, + 0.0000000000001, + 0.00000000000001, + 0.000000000000001 }; @@ -179,6 +179,9 @@ inline uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* unsigned int cur = 0; uint64_t value = 0; + if ( *in < '0' || *in > '9' ) + throw std::invalid_argument(std::string("The string \"") + in + "\" cannot be converted into a value."); + bool running = true; while ( running ) { @@ -188,7 +191,7 @@ inline uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* const uint64_t new_value = ( value * 10 ) + ( *in - '0' ); if (new_value < value) /* numeric overflow, we rely on you */ - return value; + throw std::overflow_error(std::string("Converting the string \"") + in + "\" into a value resulted in overflow."); value = new_value; @@ -224,7 +227,7 @@ inline uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* // If you find any bugs, please send them to me, niko (at) irrlicht3d.org. // ------------------------------------------------------------------------------------ template -inline const char* fast_atoreal_move( const char* c, Real& out) +inline const char* fast_atoreal_move( const char* c, Real& out, bool check_comma = true) { Real f; @@ -234,7 +237,7 @@ inline const char* fast_atoreal_move( const char* c, Real& out) } f = static_cast( strtoul10_64 ( c, &c) ); - if (*c == '.' || (c[0] == ',' && c[1] >= '0' && c[1] <= '9')) // allow for commas, too + if (*c == '.' || (check_comma && c[0] == ',' && c[1] >= '0' && c[1] <= '9')) // allow for commas, too { ++c; @@ -270,7 +273,7 @@ inline const char* fast_atoreal_move( const char* c, Real& out) if (einv) { exp = -exp; } - f *= pow(static_cast(10.0f), exp); + f *= pow(static_cast(10.0), exp); } if (inv) { diff --git a/code/irrXMLWrapper.h b/code/irrXMLWrapper.h index f5e9c3059..569347e2b 100644 --- a/code/irrXMLWrapper.h +++ b/code/irrXMLWrapper.h @@ -81,12 +81,22 @@ public: // Map the buffer into memory and convert it to UTF8. IrrXML provides its // own conversion, which is merely a cast from uintNN_t to uint8_t. Thus, // it is not suitable for our purposes and we have to do it BEFORE IrrXML - // gets the buffer. Sadly, this forces as to map the whole file into + // gets the buffer. Sadly, this forces us to map the whole file into // memory. data.resize(stream->FileSize()); stream->Read(&data[0],data.size(),1); + // Remove null characters from the input sequence otherwise the parsing will utterly fail + unsigned int size = 0; + unsigned int size_max = data.size(); + for(unsigned int i = 0; i < size_max; i++) { + if(data[i] != '\0') { + data[size++] = data[i]; + } + } + data.resize(size); + BaseImporter::ConvertToUTF8(data); } diff --git a/contrib/irrXML/CXMLReaderImpl.h b/contrib/irrXML/CXMLReaderImpl.h index 6c3afb89c..d2472b28b 100644 --- a/contrib/irrXML/CXMLReaderImpl.h +++ b/contrib/irrXML/CXMLReaderImpl.h @@ -215,7 +215,7 @@ private: { char_type* start = P; - // more forward until '<' found + // move forward until '<' found while(*P != L'<' && *P) ++P; diff --git a/contrib/zlib/zconf.h.included b/contrib/zlib/zconf.h.included new file mode 100644 index 000000000..9ccbb0a6f --- /dev/null +++ b/contrib/zlib/zconf.h.included @@ -0,0 +1,513 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2013 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H +/* #undef Z_PREFIX */ +/* #undef Z_HAVE_UNISTD_H */ + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET + +/* all linked symbols */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_bits z__tr_flush_bits +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# endif +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePending z_deflatePending +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# ifdef _WIN32 +# define gzopen_w z_gzopen_w +# endif +# define gzprintf z_gzprintf +# define gzvprintf z_gzvprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzwrite z_gzwrite +# endif +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetHeader z_inflateGetHeader +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateSetDictionary z_inflateSetDictionary +# define inflateGetDictionary z_inflateGetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflateResetKeep z_inflateResetKeep +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# ifndef Z_SOLO +# define uncompress z_uncompress +# endif +# define zError z_zError +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# ifndef Z_SOLO +# define gzFile z_gzFile +# endif +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +#if defined(ZLIB_CONST) && !defined(z_const) +# define z_const const +#else +# define z_const +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +#ifndef Z_ARG /* function prototypes for stdarg */ +# if defined(STDC) || defined(Z_HAVE_STDARG_H) +# define Z_ARG(args) args +# else +# define Z_ARG(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +# include +# if (UINT_MAX == 0xffffffffUL) +# define Z_U4 unsigned +# elif (ULONG_MAX == 0xffffffffUL) +# define Z_U4 unsigned long +# elif (USHRT_MAX == 0xffffffffUL) +# define Z_U4 unsigned short +# endif +#endif + +#ifdef Z_U4 + typedef Z_U4 z_crc_t; +#else + typedef unsigned long z_crc_t; +#endif + +#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H +#endif + +#ifdef STDC +# ifndef Z_SOLO +# include /* for off_t */ +# endif +#endif + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +# include /* for va_list */ +# endif +#endif + +#ifdef _WIN32 +# ifndef Z_SOLO +# include /* for wchar_t */ +# endif +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) +# define Z_HAVE_UNISTD_H +#endif +#ifndef Z_SOLO +# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +# endif +#endif + +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +# define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +# define Z_LARGE64 +#endif + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +# define Z_WANT64 +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long +#endif + +#if !defined(_WIN32) && defined(Z_LARGE64) +# define z_off64_t off64_t +#else +# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +# define z_off64_t __int64 +# else +# define z_off64_t z_off_t +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/include/assimp/IOStream.hpp b/include/assimp/IOStream.hpp index 54684442d..72f2e6611 100644 --- a/include/assimp/IOStream.hpp +++ b/include/assimp/IOStream.hpp @@ -61,7 +61,10 @@ namespace Assimp { * to the Importer. If you implement this interface, be sure to also provide an * implementation for IOSystem that creates instances of your custom IO class. */ -class ASSIMP_API IOStream : public Intern::AllocateFromAssimpHeap +class ASSIMP_API IOStream +#ifndef SWIG + : public Intern::AllocateFromAssimpHeap +#endif { protected: /** Constructor protected, use IOSystem::Open() to create an instance. */ diff --git a/include/assimp/IOSystem.hpp b/include/assimp/IOSystem.hpp index 76135146b..197988f72 100644 --- a/include/assimp/IOSystem.hpp +++ b/include/assimp/IOSystem.hpp @@ -64,7 +64,10 @@ class IOStream; * supply a custom implementation for IOStream. * * @see Importer::SetIOHandler() */ -class ASSIMP_API IOSystem : public Intern::AllocateFromAssimpHeap +class ASSIMP_API IOSystem +#ifndef SWIG + : public Intern::AllocateFromAssimpHeap +#endif { public: diff --git a/include/assimp/Importer.hpp b/include/assimp/Importer.hpp index e0d55d4da..5e7797b99 100644 --- a/include/assimp/Importer.hpp +++ b/include/assimp/Importer.hpp @@ -230,6 +230,13 @@ public: void SetPropertyString(const char* szName, const std::string& sValue, bool* bWasExisting = NULL); + // ------------------------------------------------------------------- + /** Set a matrix configuration property. + * @see SetPropertyInteger() + */ + void SetPropertyMatrix(const char* szName, const aiMatrix4x4& sValue, + bool* bWasExisting = NULL); + // ------------------------------------------------------------------- /** Get a configuration property. * @param szName Name of the property. All supported properties @@ -270,9 +277,18 @@ public: * The return value remains valid until the property is modified. * @see GetPropertyInteger() */ - const std::string& GetPropertyString(const char* szName, + const std::string GetPropertyString(const char* szName, const std::string& sErrorReturn = "") const; + // ------------------------------------------------------------------- + /** Get a matrix configuration property + * + * The return value remains valid until the property is modified. + * @see GetPropertyInteger() + */ + const aiMatrix4x4 GetPropertyMatrix(const char* szName, + const aiMatrix4x4& sErrorReturn = aiMatrix4x4()) const; + // ------------------------------------------------------------------- /** Supplies a custom IO handler to the importer to use to open and * access files. If you need the importer to use custion IO logic to diff --git a/include/assimp/LogStream.hpp b/include/assimp/LogStream.hpp index afd35a2fc..25b1c65f5 100644 --- a/include/assimp/LogStream.hpp +++ b/include/assimp/LogStream.hpp @@ -53,8 +53,11 @@ class IOSystem; * Several default implementations are provided, see #aiDefaultLogStream for more * details. Writing your own implementation of LogStream is just necessary if these * are not enough for your purpose. */ -class ASSIMP_API LogStream - : public Intern::AllocateFromAssimpHeap { +class ASSIMP_API LogStream +#ifndef SWIG + : public Intern::AllocateFromAssimpHeap +#endif +{ protected: /** @brief Default constructor */ LogStream() { diff --git a/include/assimp/Logger.hpp b/include/assimp/Logger.hpp index 1c3d224ea..a30b5b0dc 100644 --- a/include/assimp/Logger.hpp +++ b/include/assimp/Logger.hpp @@ -56,8 +56,11 @@ class LogStream; * Assimp provides a default implementation and uses it for almost all * logging stuff ('DefaultLogger'). This class defines just basic logging * behaviour and is not of interest for you. Instead, take a look at #DefaultLogger. */ -class ASSIMP_API Logger - : public Intern::AllocateFromAssimpHeap { +class ASSIMP_API Logger +#ifndef SWIG + : public Intern::AllocateFromAssimpHeap +#endif +{ public: // ---------------------------------------------------------------------- diff --git a/include/assimp/ProgressHandler.hpp b/include/assimp/ProgressHandler.hpp index 26f79566a..31c746c59 100644 --- a/include/assimp/ProgressHandler.hpp +++ b/include/assimp/ProgressHandler.hpp @@ -51,8 +51,11 @@ namespace Assimp { * * Each #Importer instance maintains its own #ProgressHandler. The default * implementation provided by Assimp doesn't do anything at all. */ -class ASSIMP_API ProgressHandler - : public Intern::AllocateFromAssimpHeap { +class ASSIMP_API ProgressHandler +#ifndef SWIG + : public Intern::AllocateFromAssimpHeap +#endif +{ protected: /** @brief Default constructor */ ProgressHandler () { diff --git a/include/assimp/ai_assert.h b/include/assimp/ai_assert.h index 3ad7fd32c..1f946d6ec 100644 --- a/include/assimp/ai_assert.h +++ b/include/assimp/ai_assert.h @@ -3,7 +3,7 @@ #ifndef AI_DEBUG_H_INC #define AI_DEBUG_H_INC -#ifdef _DEBUG +#ifdef ASSIMP_BUILD_DEBUG # include # define ai_assert(expression) assert(expression) #else diff --git a/include/assimp/cimport.h b/include/assimp/cimport.h index 237e65c29..adc27502b 100644 --- a/include/assimp/cimport.h +++ b/include/assimp/cimport.h @@ -79,6 +79,7 @@ struct aiLogStream * @see aiSetPropertyInteger * @see aiSetPropertyFloat * @see aiSetPropertyString + * @see aiSetPropertyMatrix */ // -------------------------------------------------------------------------------- struct aiPropertyStore { char sentinel; }; @@ -397,6 +398,23 @@ ASSIMP_API void aiSetImportPropertyString( const char* szName, const C_STRUCT aiString* st); +// -------------------------------------------------------------------------------- +/** Set a matrix property. + * + * This is the C-version of #Assimp::Importer::SetPropertyMatrix(). In the C + * interface, properties are always shared by all imports. It is not possible to + * specify them per import. + * + * @param property store to modify. Use #aiCreatePropertyStore to obtain a store. + * @param szName Name of the configuration property to be set. All supported + * public properties are defined in the config.h header file (#AI_CONFIG_XXX). + * @param value New value for the property + */ +ASSIMP_API void aiSetImportPropertyMatrix( + C_STRUCT aiPropertyStore* store, + const char* szName, + const C_STRUCT aiMatrix4x4* mat); + // -------------------------------------------------------------------------------- /** Construct a quaternion from a 3x3 rotation matrix. * @param quat Receives the output quaternion. diff --git a/include/assimp/color4.h b/include/assimp/color4.h index 4fb8941ee..bd8ff6fb4 100644 --- a/include/assimp/color4.h +++ b/include/assimp/color4.h @@ -74,6 +74,7 @@ public: // comparison bool operator == (const aiColor4t& other) const; bool operator != (const aiColor4t& other) const; + bool operator < (const aiColor4t& other) const; // color tuple access, rgba order inline TReal operator[](unsigned int i) const; diff --git a/include/assimp/color4.inl b/include/assimp/color4.inl index f4f9126de..ac70d7b09 100644 --- a/include/assimp/color4.inl +++ b/include/assimp/color4.inl @@ -94,6 +94,23 @@ AI_FORCE_INLINE bool aiColor4t::operator!= (const aiColor4t& other } // ------------------------------------------------------------------------------------------------ template +AI_FORCE_INLINE bool aiColor4t::operator< (const aiColor4t& other) const { + return r < other.r || ( + r == other.r && ( + g < other.g || ( + g == other.g && ( + b < other.b || ( + b == other.b && ( + a < other.a + ) + ) + ) + ) + ) + ); +} +// ------------------------------------------------------------------------------------------------ +template AI_FORCE_INLINE aiColor4t operator + (const aiColor4t& v1, const aiColor4t& v2) { return aiColor4t( v1.r + v2.r, v1.g + v2.g, v1.b + v2.b, v1.a + v2.a); } diff --git a/include/assimp/config.h b/include/assimp/config.h index 8683cc385..034652fa8 100644 --- a/include/assimp/config.h +++ b/include/assimp/config.h @@ -233,6 +233,25 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define AI_CONFIG_PP_PTV_NORMALIZE \ "PP_PTV_NORMALIZE" +// --------------------------------------------------------------------------- +/** @brief Configures the #aiProcess_PretransformVertices step to use + * a users defined matrix as the scene root node transformation before + * transforming vertices. + * Property type: bool. Default value: false. + */ +#define AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION \ + "PP_PTV_ADD_ROOT_TRANSFORMATION" + +// --------------------------------------------------------------------------- +/** @brief Configures the #aiProcess_PretransformVertices step to use + * a users defined matrix as the scene root node transformation before + * transforming vertices. This property correspond to the 'a1' component + * of the transformation matrix. + * Property type: aiMatrix4x4. + */ +#define AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION \ + "PP_PTV_ROOT_TRANSFORMATION" + // --------------------------------------------------------------------------- /** @brief Configures the #aiProcess_FindDegenerates step to * remove degenerated primitives from the import - immediately. diff --git a/include/assimp/defs.h b/include/assimp/defs.h index aeae0778f..e0019f893 100644 --- a/include/assimp/defs.h +++ b/include/assimp/defs.h @@ -238,11 +238,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # define ASSIMP_BUILD_SINGLETHREADED #endif -#ifndef ASSIMP_BUILD_SINGLETHREADED -# define AI_C_THREADSAFE -#endif // !! ASSIMP_BUILD_SINGLETHREADED - -#ifdef _DEBUG +#if defined(_DEBUG) || ! defined(NDEBUG) # define ASSIMP_BUILD_DEBUG #endif diff --git a/include/assimp/material.h b/include/assimp/material.h index 9151c8ec5..2c8ad1d5c 100644 --- a/include/assimp/material.h +++ b/include/assimp/material.h @@ -1473,6 +1473,18 @@ ASSIMP_API C_ENUM aiReturn aiGetMaterialColor(const C_STRUCT aiMaterial* pMat, C_STRUCT aiColor4D* pOut); +// --------------------------------------------------------------------------- +/** @brief Retrieve a aiUVTransform value from the material property table +* +* See the sample for aiGetMaterialFloat for more information*/ +// --------------------------------------------------------------------------- +ASSIMP_API C_ENUM aiReturn aiGetMaterialUVTransform(const C_STRUCT aiMaterial* pMat, + const char* pKey, + unsigned int type, + unsigned int index, + C_STRUCT aiUVTransform* pOut); + + // --------------------------------------------------------------------------- /** @brief Retrieve a string from the material property table * diff --git a/include/assimp/material.inl b/include/assimp/material.inl index ffb000937..3c269cd1b 100644 --- a/include/assimp/material.inl +++ b/include/assimp/material.inl @@ -167,6 +167,12 @@ inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type, { return aiGetMaterialString(this,pKey,type,idx,&pOut); } +// --------------------------------------------------------------------------- +inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type, + unsigned int idx,aiUVTransform& pOut) const +{ + return aiGetMaterialUVTransform(this,pKey,type,idx,&pOut); +} // --------------------------------------------------------------------------- diff --git a/include/assimp/matrix3x3.h b/include/assimp/matrix3x3.h index 029284111..3881bceec 100644 --- a/include/assimp/matrix3x3.h +++ b/include/assimp/matrix3x3.h @@ -90,8 +90,10 @@ public: const TReal* operator[] (unsigned int p_iIndex) const; // comparison operators - bool operator== (const aiMatrix4x4t m) const; - bool operator!= (const aiMatrix4x4t m) const; + bool operator== (const aiMatrix4x4t& m) const; + bool operator!= (const aiMatrix4x4t& m) const; + + bool Equal(const aiMatrix4x4t& m, TReal epsilon = 1e-6) const; template operator aiMatrix3x3t () const; diff --git a/include/assimp/matrix3x3.inl b/include/assimp/matrix3x3.inl index f47d2b78d..b6caef5d1 100644 --- a/include/assimp/matrix3x3.inl +++ b/include/assimp/matrix3x3.inl @@ -50,6 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "matrix4x4.h" #include +#include #include // ------------------------------------------------------------------------------------------------ @@ -113,7 +114,7 @@ inline const TReal* aiMatrix3x3t::operator[] (unsigned int p_iIndex) cons // ------------------------------------------------------------------------------------------------ template -inline bool aiMatrix3x3t::operator== (const aiMatrix4x4t m) const +inline bool aiMatrix3x3t::operator== (const aiMatrix4x4t& m) const { return a1 == m.a1 && a2 == m.a2 && a3 == m.a3 && b1 == m.b1 && b2 == m.b2 && b3 == m.b3 && @@ -122,11 +123,26 @@ inline bool aiMatrix3x3t::operator== (const aiMatrix4x4t m) const // ------------------------------------------------------------------------------------------------ template -inline bool aiMatrix3x3t::operator!= (const aiMatrix4x4t m) const +inline bool aiMatrix3x3t::operator!= (const aiMatrix4x4t& m) const { return !(*this == m); } +// --------------------------------------------------------------------------- +template +inline bool aiMatrix3x3t::Equal(const aiMatrix4x4t& m, TReal epsilon) const { + return + std::abs(a1 - m.a1) <= epsilon && + std::abs(a2 - m.a2) <= epsilon && + std::abs(a3 - m.a3) <= epsilon && + std::abs(b1 - m.b1) <= epsilon && + std::abs(b2 - m.b2) <= epsilon && + std::abs(b3 - m.b3) <= epsilon && + std::abs(c1 - m.c1) <= epsilon && + std::abs(c2 - m.c2) <= epsilon && + std::abs(c3 - m.c3) <= epsilon; +} + // ------------------------------------------------------------------------------------------------ template inline aiMatrix3x3t& aiMatrix3x3t::Transpose() diff --git a/include/assimp/matrix4x4.h b/include/assimp/matrix4x4.h index 6041bac1a..7c6905107 100644 --- a/include/assimp/matrix4x4.h +++ b/include/assimp/matrix4x4.h @@ -78,6 +78,14 @@ public: /** construction from 3x3 matrix, remaining elements are set to identity */ explicit aiMatrix4x4t( const aiMatrix3x3t& m); + + /** construction from position, rotation and scaling components + * @param scaling The scaling for the x,y,z axes + * @param rotation The rotation as a hamilton quaternion + * @param position The position for the x,y,z axes + */ + aiMatrix4x4t(aiVector3t& scaling, aiQuaterniont& rotation, + aiVector3t& position); public: @@ -86,8 +94,10 @@ public: const TReal* operator[] (unsigned int p_iIndex) const; // comparison operators - bool operator== (const aiMatrix4x4t m) const; - bool operator!= (const aiMatrix4x4t m) const; + bool operator== (const aiMatrix4x4t& m) const; + bool operator!= (const aiMatrix4x4t& m) const; + + bool Equal(const aiMatrix4x4t& m, TReal epsilon = 1e-6) const; // matrix multiplication. aiMatrix4x4t& operator *= (const aiMatrix4x4t& m); diff --git a/include/assimp/matrix4x4.inl b/include/assimp/matrix4x4.inl index 589129b10..2d30796ab 100644 --- a/include/assimp/matrix4x4.inl +++ b/include/assimp/matrix4x4.inl @@ -7,8 +7,8 @@ Copyright (c) 2006-2012, assimp 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 +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 @@ -25,16 +25,16 @@ conditions are met: derived from this software without specific prior written permission of the assimp team. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +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 +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 +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 +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. --------------------------------------------------------------------------- */ @@ -52,19 +52,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "quaternion.h" #include -#include +#include #ifdef __cplusplus # include #else # include -#endif +#endif // ---------------------------------------------------------------------------------------- template -aiMatrix4x4t ::aiMatrix4x4t () : - a1(1.0f), a2(), a3(), a4(), - b1(), b2(1.0f), b3(), b4(), +aiMatrix4x4t ::aiMatrix4x4t () : + a1(1.0f), a2(), a3(), a4(), + b1(), b2(1.0f), b3(), b4(), c1(), c2(), c3(1.0f), c4(), d1(), d2(), d3(), d4(1.0f) { @@ -76,13 +76,13 @@ template aiMatrix4x4t ::aiMatrix4x4t (TReal _a1, TReal _a2, TReal _a3, TReal _a4, TReal _b1, TReal _b2, TReal _b3, TReal _b4, TReal _c1, TReal _c2, TReal _c3, TReal _c4, - TReal _d1, TReal _d2, TReal _d3, TReal _d4) : - a1(_a1), a2(_a2), a3(_a3), a4(_a4), - b1(_b1), b2(_b2), b3(_b3), b4(_b4), + TReal _d1, TReal _d2, TReal _d3, TReal _d4) : + a1(_a1), a2(_a2), a3(_a3), a4(_a4), + b1(_b1), b2(_b2), b3(_b3), b4(_b4), c1(_c1), c2(_c2), c3(_c3), c4(_c4), d1(_d1), d2(_d2), d3(_d3), d4(_d4) { - + } // ------------------------------------------------------------------------------------------------ @@ -107,6 +107,34 @@ inline aiMatrix4x4t::aiMatrix4x4t (const aiMatrix3x3t& m) d1 = static_cast(0.0); d2 = static_cast(0.0); d3 = static_cast(0.0); d4 = static_cast(1.0); } +// ---------------------------------------------------------------------------------------- +template +inline aiMatrix4x4t::aiMatrix4x4t (aiVector3t& scaling, aiQuaterniont& rotation, aiVector3t& position) +{ + // build a 3x3 rotation matrix + aiMatrix3x3t m = rotation.GetMatrix(); + + a1 = m.a1 * scaling.x; + a2 = m.a2 * scaling.x; + a3 = m.a3 * scaling.x; + a4 = position.x; + + b1 = m.b1 * scaling.y; + b2 = m.b2 * scaling.y; + b3 = m.b3 * scaling.y; + b4 = position.y; + + c1 = m.c1 * scaling.z; + c2 = m.c2 * scaling.z; + c3 = m.c3 * scaling.z; + c4= position.z; + + d1 = static_cast(0.0); + d2 = static_cast(0.0); + d3 = static_cast(0.0); + d4 = static_cast(1.0); +} + // ---------------------------------------------------------------------------------------- template inline aiMatrix4x4t& aiMatrix4x4t::operator *= (const aiMatrix4x4t& m) @@ -160,10 +188,10 @@ inline aiMatrix4x4t& aiMatrix4x4t::Transpose() template inline TReal aiMatrix4x4t::Determinant() const { - return a1*b2*c3*d4 - a1*b2*c4*d3 + a1*b3*c4*d2 - a1*b3*c2*d4 - + a1*b4*c2*d3 - a1*b4*c3*d2 - a2*b3*c4*d1 + a2*b3*c1*d4 - - a2*b4*c1*d3 + a2*b4*c3*d1 - a2*b1*c3*d4 + a2*b1*c4*d3 - + a3*b4*c1*d2 - a3*b4*c2*d1 + a3*b1*c2*d4 - a3*b1*c4*d2 + return a1*b2*c3*d4 - a1*b2*c4*d3 + a1*b3*c4*d2 - a1*b3*c2*d4 + + a1*b4*c2*d3 - a1*b4*c3*d2 - a2*b3*c4*d1 + a2*b3*c1*d4 + - a2*b4*c1*d3 + a2*b4*c3*d1 - a2*b1*c3*d4 + a2*b1*c4*d3 + + a3*b4*c1*d2 - a3*b4*c2*d1 + a3*b1*c2*d4 - a3*b1*c4*d2 + a3*b2*c4*d1 - a3*b2*c1*d4 - a4*b1*c2*d3 + a4*b1*c3*d2 - a4*b2*c3*d1 + a4*b2*c1*d3 - a4*b3*c1*d2 + a4*b3*c2*d1; } @@ -174,7 +202,7 @@ inline aiMatrix4x4t& aiMatrix4x4t::Inverse() { // Compute the reciprocal determinant const TReal det = Determinant(); - if(det == static_cast(0.0)) + if(det == static_cast(0.0)) { // Matrix not invertible. Setting all elements to nan is not really // correct in a mathematical sense but it is easy to debug for the @@ -207,7 +235,7 @@ inline aiMatrix4x4t& aiMatrix4x4t::Inverse() res.d1 = -invdet * (b1 * (c2 * d3 - c3 * d2) + b2 * (c3 * d1 - c1 * d3) + b3 * (c1 * d2 - c2 * d1)); res.d2 = invdet * (a1 * (c2 * d3 - c3 * d2) + a2 * (c3 * d1 - c1 * d3) + a3 * (c1 * d2 - c2 * d1)); res.d3 = -invdet * (a1 * (b2 * d3 - b3 * d2) + a2 * (b3 * d1 - b1 * d3) + a3 * (b1 * d2 - b2 * d1)); - res.d4 = invdet * (a1 * (b2 * c3 - b3 * c2) + a2 * (b3 * c1 - b1 * c3) + a3 * (b1 * c2 - b2 * c1)); + res.d4 = invdet * (a1 * (b2 * c3 - b3 * c2) + a2 * (b3 * c1 - b1 * c3) + a3 * (b1 * c2 - b2 * c1)); *this = res; return *this; @@ -231,7 +259,7 @@ inline const TReal* aiMatrix4x4t::operator[](unsigned int p_iIndex) const // ---------------------------------------------------------------------------------------- template -inline bool aiMatrix4x4t::operator== (const aiMatrix4x4t m) const +inline bool aiMatrix4x4t::operator== (const aiMatrix4x4t& m) const { return (a1 == m.a1 && a2 == m.a2 && a3 == m.a3 && a4 == m.a4 && b1 == m.b1 && b2 == m.b2 && b3 == m.b3 && b4 == m.b4 && @@ -241,11 +269,33 @@ inline bool aiMatrix4x4t::operator== (const aiMatrix4x4t m) const // ---------------------------------------------------------------------------------------- template -inline bool aiMatrix4x4t::operator!= (const aiMatrix4x4t m) const +inline bool aiMatrix4x4t::operator!= (const aiMatrix4x4t& m) const { return !(*this == m); } +// --------------------------------------------------------------------------- +template +inline bool aiMatrix4x4t::Equal(const aiMatrix4x4t& m, TReal epsilon) const { + return + std::abs(a1 - m.a1) <= epsilon && + std::abs(a2 - m.a2) <= epsilon && + std::abs(a3 - m.a3) <= epsilon && + std::abs(a4 - m.a4) <= epsilon && + std::abs(b1 - m.b1) <= epsilon && + std::abs(b2 - m.b2) <= epsilon && + std::abs(b3 - m.b3) <= epsilon && + std::abs(b4 - m.b4) <= epsilon && + std::abs(c1 - m.c1) <= epsilon && + std::abs(c2 - m.c2) <= epsilon && + std::abs(c3 - m.c3) <= epsilon && + std::abs(c4 - m.c4) <= epsilon && + std::abs(d1 - m.d1) <= epsilon && + std::abs(d2 - m.d2) <= epsilon && + std::abs(d3 - m.d3) <= epsilon && + std::abs(d4 - m.d4) <= epsilon; +} + // ---------------------------------------------------------------------------------------- template inline void aiMatrix4x4t::Decompose (aiVector3t& scaling, aiQuaterniont& rotation, @@ -373,9 +423,9 @@ inline bool aiMatrix4x4t::IsIdentity() const d1 <= epsilon && d1 >= -epsilon && d2 <= epsilon && d2 >= -epsilon && d3 <= epsilon && d3 >= -epsilon && - a1 <= 1.f+epsilon && a1 >= 1.f-epsilon && - b2 <= 1.f+epsilon && b2 >= 1.f-epsilon && - c3 <= 1.f+epsilon && c3 >= 1.f-epsilon && + a1 <= 1.f+epsilon && a1 >= 1.f-epsilon && + b2 <= 1.f+epsilon && b2 >= 1.f-epsilon && + c3 <= 1.f+epsilon && c3 >= 1.f-epsilon && d4 <= 1.f+epsilon && d4 >= 1.f-epsilon); } @@ -477,9 +527,9 @@ inline aiMatrix4x4t& aiMatrix4x4t::Scaling( const aiVector3t -inline aiMatrix4x4t& aiMatrix4x4t::FromToMatrix(const aiVector3t& from, +inline aiMatrix4x4t& aiMatrix4x4t::FromToMatrix(const aiVector3t& from, const aiVector3t& to, aiMatrix4x4t& mtx) -{ +{ aiMatrix3x3t m3; aiMatrix3x3t::FromToMatrix(from,to,m3); mtx = aiMatrix4x4t(m3); diff --git a/include/assimp/mesh.h b/include/assimp/mesh.h index 01d5baf7c..e283e4105 100644 --- a/include/assimp/mesh.h +++ b/include/assimp/mesh.h @@ -620,7 +620,7 @@ struct aiMesh , mBitangents( NULL ) , mFaces( NULL ) , mNumBones( 0 ) - , mBones( 0 ) + , mBones( NULL ) , mMaterialIndex( 0 ) , mNumAnimMeshes( 0 ) , mAnimMeshes( NULL ) diff --git a/include/assimp/metadata.h b/include/assimp/metadata.h index ac55d2395..a16b4062b 100644 --- a/include/assimp/metadata.h +++ b/include/assimp/metadata.h @@ -64,7 +64,9 @@ enum aiMetadataType AI_AISTRING = 4, AI_AIVECTOR3D = 5, +#ifndef SWIG FORCE_32BIT = INT_MAX +#endif }; diff --git a/include/assimp/quaternion.h b/include/assimp/quaternion.h index 112d5766d..9c43499c1 100644 --- a/include/assimp/quaternion.h +++ b/include/assimp/quaternion.h @@ -79,6 +79,8 @@ public: bool operator== (const aiQuaterniont& o) const; bool operator!= (const aiQuaterniont& o) const; + bool Equal(const aiQuaterniont& o, TReal epsilon = 1e-6) const; + public: /** Normalize the quaternion */ diff --git a/include/assimp/quaternion.inl b/include/assimp/quaternion.inl index 9113848b8..fb07a4b3e 100644 --- a/include/assimp/quaternion.inl +++ b/include/assimp/quaternion.inl @@ -48,6 +48,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifdef __cplusplus #include "quaternion.h" +#include + // --------------------------------------------------------------------------- template bool aiQuaterniont::operator== (const aiQuaterniont& o) const @@ -62,7 +64,15 @@ bool aiQuaterniont::operator!= (const aiQuaterniont& o) const return !(*this == o); } - +// --------------------------------------------------------------------------- +template +inline bool aiQuaterniont::Equal(const aiQuaterniont& o, TReal epsilon) const { + return + std::abs(x - o.x) <= epsilon && + std::abs(y - o.y) <= epsilon && + std::abs(z - o.z) <= epsilon && + std::abs(w - o.w) <= epsilon; +} // --------------------------------------------------------------------------- // Constructs a quaternion from a rotation matrix diff --git a/include/assimp/scene.h b/include/assimp/scene.h index 3223759ff..506759419 100644 --- a/include/assimp/scene.h +++ b/include/assimp/scene.h @@ -122,14 +122,14 @@ struct aiNode #ifdef __cplusplus /** Constructor */ aiNode() - // set all members to zero by default - : mName() - , mParent() - , mNumChildren() - , mChildren() - , mNumMeshes() - , mMeshes() - , mMetaData() + // set all members to zero by default + : mName("") + , mParent(NULL) + , mNumChildren(0) + , mChildren(NULL) + , mNumMeshes(0) + , mMeshes(NULL) + , mMetaData(NULL) { } @@ -137,13 +137,13 @@ struct aiNode /** Construction from a specific name */ aiNode(const std::string& name) // set all members to zero by default - : mName(name) - , mParent() - , mNumChildren() - , mChildren() - , mNumMeshes() - , mMeshes() - , mMetaData() + : mName(name) + , mParent(NULL) + , mNumChildren(0) + , mChildren(NULL) + , mNumMeshes(0) + , mMeshes(NULL) + , mMetaData(NULL) { } @@ -378,10 +378,10 @@ struct aiScene #ifdef __cplusplus //! Default constructor - set everything to 0/NULL - aiScene(); + ASSIMP_API aiScene(); //! Destructor - ~aiScene(); + ASSIMP_API ~aiScene(); //! Check whether the scene contains meshes //! Unless no special scene flags are set this will always be true. diff --git a/include/assimp/types.h b/include/assimp/types.h index cbbf8fff5..822490a45 100644 --- a/include/assimp/types.h +++ b/include/assimp/types.h @@ -174,6 +174,16 @@ struct aiColor3D bool operator != (const aiColor3D& other) const {return r != other.r || g != other.g || b != other.b;} + /** Component-wise comparison */ + // TODO: add epsilon? + bool operator < (const aiColor3D& other) const { + return r < other.r || ( + r == other.r && (g < other.g || + (g == other.g && b < other.b) + ) + ); + } + /** Component-wise addition */ aiColor3D operator+(const aiColor3D& c) const { return aiColor3D(r+c.r,g+c.g,b+c.b); @@ -247,7 +257,7 @@ struct aiString { data[0] = '\0'; -#ifdef _DEBUG +#ifdef ASSIMP_BUILD_DEBUG // Debug build: overwrite the string on its full length with ESC (27) memset(data+1,27,MAXLEN-1); #endif @@ -334,7 +344,7 @@ struct aiString length = 0; data[0] = '\0'; -#ifdef _DEBUG +#ifdef ASSIMP_BUILD_DEBUG // Debug build: overwrite the string on its full length with ESC (27) memset(data+1,27,MAXLEN-1); #endif diff --git a/include/assimp/vector2.h b/include/assimp/vector2.h index f5e4b7c5e..d033e5a15 100644 --- a/include/assimp/vector2.h +++ b/include/assimp/vector2.h @@ -43,13 +43,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef AI_VECTOR2D_H_INC #define AI_VECTOR2D_H_INC - + #ifdef __cplusplus # include #else # include #endif - + #include "./Compiler/pushpack1.h" // ---------------------------------------------------------------------------------- @@ -87,6 +87,8 @@ public: bool operator== (const aiVector2t& other) const; bool operator!= (const aiVector2t& other) const; + bool Equal(const aiVector2t& other, TReal epsilon = 1e-6) const; + aiVector2t& operator= (TReal f); const aiVector2t SymMul(const aiVector2t& o); diff --git a/include/assimp/vector2.inl b/include/assimp/vector2.inl index 04d11c56c..e357a5e7a 100644 --- a/include/assimp/vector2.inl +++ b/include/assimp/vector2.inl @@ -48,6 +48,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifdef __cplusplus #include "vector2.h" +#include + // ------------------------------------------------------------------------------------------------ template template @@ -131,6 +133,14 @@ bool aiVector2t::operator!= (const aiVector2t& other) const { return x != other.x || y != other.y; } +// --------------------------------------------------------------------------- +template +bool aiVector2t::Equal(const aiVector2t& other, TReal epsilon) const { + return + std::abs(x - other.x) <= epsilon && + std::abs(y - other.y) <= epsilon; +} + // ------------------------------------------------------------------------------------------------ template aiVector2t& aiVector2t::operator= (TReal f) { diff --git a/include/assimp/vector3.h b/include/assimp/vector3.h index 7b5269c9c..9edaf5bf6 100644 --- a/include/assimp/vector3.h +++ b/include/assimp/vector3.h @@ -43,13 +43,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef AI_VECTOR3D_H_INC #define AI_VECTOR3D_H_INC - + #ifdef __cplusplus # include #else # include #endif - + #include "./Compiler/pushpack1.h" #ifdef __cplusplus @@ -89,6 +89,8 @@ public: bool operator== (const aiVector3t& other) const; bool operator!= (const aiVector3t& other) const; + bool Equal(const aiVector3t& other, TReal epsilon = 1e-6) const; + template operator aiVector3t () const; diff --git a/include/assimp/vector3.inl b/include/assimp/vector3.inl index 63c91480a..93f317645 100644 --- a/include/assimp/vector3.inl +++ b/include/assimp/vector3.inl @@ -48,6 +48,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifdef __cplusplus #include "vector3.h" +#include + // ------------------------------------------------------------------------------------------------ /** Transformation of a vector by a 3x3 matrix */ template @@ -147,6 +149,14 @@ template AI_FORCE_INLINE bool aiVector3t::operator!= (const aiVector3t& other) const { return x != other.x || y != other.y || z != other.z; } +// --------------------------------------------------------------------------- +template +AI_FORCE_INLINE bool aiVector3t::Equal(const aiVector3t& other, TReal epsilon) const { + return + std::abs(x - other.x) <= epsilon && + std::abs(y - other.y) <= epsilon && + std::abs(z - other.z) <= epsilon; +} // ------------------------------------------------------------------------------------------------ template AI_FORCE_INLINE const aiVector3t aiVector3t::SymMul(const aiVector3t& o) { diff --git a/tools/assimp_cmd/Main.cpp b/tools/assimp_cmd/Main.cpp index fe2853e7a..c5c1de6fd 100644 --- a/tools/assimp_cmd/Main.cpp +++ b/tools/assimp_cmd/Main.cpp @@ -51,7 +51,7 @@ const char* AICMD_MSG_ABOUT = " -- Commandline toolchain --\n" "------------------------------------------------------ \n\n" -"Version %i.%i-%s%s%s%s%s (SVNREV %i)\n\n"; +"Version %i.%i %s%s%s%s%s(SVNREV %i)\n\n"; const char* AICMD_MSG_HELP = "assimp \n\n" diff --git a/tools/assimp_view/MessageProc.cpp b/tools/assimp_view/MessageProc.cpp index 26753f846..c32cbde61 100644 --- a/tools/assimp_view/MessageProc.cpp +++ b/tools/assimp_view/MessageProc.cpp @@ -1041,27 +1041,35 @@ void DoExport(size_t formatId) char szFileName[MAX_PATH*2]; DWORD dwTemp; if(ERROR_SUCCESS == RegQueryValueEx(g_hRegistry,"ModelExportDest",NULL,NULL,(BYTE*)szFileName,&dwTemp)) { + ai_assert(dwTemp == MAX_PATH + 1); + ai_assert(strlen(szFileName) <= MAX_PATH); + // invent a nice default file name char* sz = std::max(strrchr(szFileName,'\\'),strrchr(szFileName,'/')); if (sz) { - strcpy(sz,std::max(strrchr(g_szFileName,'\\'),strrchr(g_szFileName,'/'))); + strncpy(sz,std::max(strrchr(g_szFileName,'\\'),strrchr(g_szFileName,'/')),MAX_PATH); } } else { // Key was not found. Use the folder where the asset comes from - strcpy(szFileName,g_szFileName); + strncpy(szFileName,g_szFileName,MAX_PATH); } // fix file extension { char * const sz = strrchr(szFileName,'.'); - if(sz) strcpy(sz+1,e->fileExtension); + if(sz) { + ai_assert((sz - &szFileName[0]) + strlen(e->fileExtension) + 1 <= MAX_PATH); + strcpy(sz+1,e->fileExtension); + } } // build the stupid info string for GetSaveFileName() - can't use sprintf() because the string must contain binary zeros. char desc[256] = {0}; char* c = strcpy(desc,e->description) + strlen(e->description)+1; c += sprintf(c,"*.%s",e->fileExtension)+1; - strcpy(c, "*.*\0"); + strcpy(c, "*.*\0"); c += 4; + + ai_assert(c - &desc[0] <= 256); const std::string ext = "."+std::string(e->fileExtension); OPENFILENAME sFilename1 = { @@ -1084,7 +1092,15 @@ void DoExport(size_t formatId) } // export the file - const aiReturn res = exp.Export(g_pcAsset->pcScene,e->id,sFinal.c_str()); + const aiReturn res = exp.Export(g_pcAsset->pcScene,e->id,sFinal.c_str(), + ppsteps | /* configurable pp steps */ + aiProcess_GenSmoothNormals | // generate smooth normal vectors if not existing + aiProcess_SplitLargeMeshes | // split large, unrenderable meshes into submeshes + aiProcess_Triangulate | // triangulate polygons with more than 3 edges + aiProcess_ConvertToLeftHanded | // convert everything to D3D left handed space + aiProcess_SortByPType | // make 'clean' meshes which consist of a single typ of primitives + 0 + ); if (res == aiReturn_SUCCESS) { CLogDisplay::Instance().AddEntry("[INFO] Exported file " + sFinal,D3DCOLOR_ARGB(0xFF,0x00,0xFF,0x00)); return;