Merge pull request #261 from terziman/master

Improvement of collada exporter & bug fixes
pull/265/head
Kim Kulling 2014-04-28 23:54:10 +02:00
commit 562dd01655
80 changed files with 2284 additions and 735 deletions

2
.gitignore vendored
View File

@ -1 +1,3 @@
build
.project
*.kdev4*

View File

@ -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 )

View File

@ -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 <boost/thread/thread.hpp>
# include <boost/thread/mutex.hpp>
#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<PropertyMap*>(p);
SetGenericProperty<aiMatrix4x4>(pp->matrices,szName,*mat,NULL);
ASSIMP_END_EXCEPTION_REGION(void);
}
// ------------------------------------------------------------------------------------------------
// Rotation matrix to quaternion
ASSIMP_API void aiCreateQuaternionFromMatrix(aiQuaternion* quat,const aiMatrix3x3* mat)

View File

@ -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;

View File

@ -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)

View File

@ -379,6 +379,43 @@ void BaseImporter::ConvertToUTF8(std::vector<char>& 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<char>& data)
@ -533,7 +570,7 @@ void BatchLoader::LoadAll()
for (std::list<LoadRequest>::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())
{

View File

@ -331,6 +331,15 @@ public: // static utilities
static void ConvertToUTF8(
std::vector<char>& 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

145
code/Bitmap.cpp 100644
View File

@ -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<typename T>
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);
}
}
}

139
code/Bitmap.h 100644
View File

@ -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

View File

@ -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

View File

@ -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} )

View File

@ -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 <ctime>
#include <set>
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<IOStream> 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 << "<COLLADA xmlns=\"http://www.collada.org/2005/11/COLLADASchema\" version=\"1.4.1\">" << 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 << "<scene>" << endstr;
PushTag();
mOutput << startstr << "<instance_visual_scene url=\"#myScene\" />" << endstr;
mOutput << startstr << "<instance_visual_scene url=\"#" + std::string(mScene->mRootNode->mName.C_Str()) + "\" />" << endstr;
PopTag();
mOutput << startstr << "</scene>" << 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 << "<asset>" << endstr;
PushTag();
mOutput << startstr << "<contributor>" << endstr;
PushTag();
mOutput << startstr << "<author>Someone</author>" << endstr;
mOutput << startstr << "<author>Assimp</author>" << endstr;
mOutput << startstr << "<authoring_tool>Assimp Collada Exporter</authoring_tool>" << endstr;
PopTag();
mOutput << startstr << "</contributor>" << endstr;
mOutput << startstr << "<created>2000-01-01T23:59:59</created>" << endstr;
mOutput << startstr << "<modified>2000-01-01T23:59:59</modified>" << endstr;
mOutput << startstr << "<unit name=\"centimeter\" meter=\"0.01\" />" << endstr;
mOutput << startstr << "<up_axis>Y_UP</up_axis>" << endstr;
mOutput << startstr << "<created>" << date_str << "</created>" << endstr;
mOutput << startstr << "<modified>" << date_str << "</modified>" << endstr;
mOutput << startstr << "<unit name=\"meter\" meter=\"" << scale << "\" />" << endstr;
mOutput << startstr << "<up_axis>" << up_axis << "</up_axis>" << endstr;
PopTag();
mOutput << startstr << "</asset>" << 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<IOStream> 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<unsigned int, std::string>::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 << "<color sid=\"" << pTypeName << "\">" << pSurface.color.r << " " << pSurface.color.g << " " << pSurface.color.b << " " << pSurface.color.a << "</color>" << endstr;
} else
{
mOutput << startstr << "<texture texture=\"" << pImageName << "\" texcoord=\"CHANNEL" << pSurface.channel << "\" />" << endstr;
if(pSurface.exist) {
mOutput << startstr << "<" << pTypeName << ">" << endstr;
PushTag();
if( pSurface.texture.empty() )
{
mOutput << startstr << "<color sid=\"" << pTypeName << "\">" << pSurface.color.r << " " << pSurface.color.g << " " << pSurface.color.b << " " << pSurface.color.a << "</color>" << endstr;
} else
{
mOutput << startstr << "<texture texture=\"" << pImageName << "\" texcoord=\"CHANNEL" << pSurface.channel << "\" />" << endstr;
}
PopTag();
mOutput << startstr << "</" << pTypeName << ">" << endstr;
}
PopTag();
mOutput << startstr << "</" << pTypeName << ">" << 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 << "<float sid=\"" << pTypeName << "\">" << pProperty.value << "</float>" << endstr;
PopTag();
mOutput << startstr << "</" << pTypeName << ">" << endstr;
}
}
// ------------------------------------------------------------------------------------------------
// Writes the material setup
void ColladaExporter::WriteMaterials()
{
materials.resize( mScene->mNumMaterials);
std::set<std::string> 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<std::string> (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<uint8_t>(*it) ) ) {
if( !isalnum( static_cast<uint8_t>(*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 << "<technique sid=\"standard\">" << endstr;
PushTag();
mOutput << startstr << "<phong>" << 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 << "<shininess>" << endstr;
PushTag();
mOutput << startstr << "<float sid=\"shininess\">" << mat.shininess << "</float>" << endstr;
PopTag();
mOutput << startstr << "</shininess>" << 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 << "</phong>" << endstr;
mOutput << startstr << "</" << mat.shading_model << ">" << endstr;
PopTag();
mOutput << startstr << "</technique>" << 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 << "<library_visual_scenes>" << endstr;
PushTag();
mOutput << startstr << "<visual_scene id=\"myScene\" name=\"myScene\">" << endstr;
mOutput << startstr << "<visual_scene id=\"" + scene_name + "\" name=\"" + scene_name + "\">" << 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 << "</visual_scene>" << 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 << "<instance_geometry url=\"#" << GetMeshId( pNode->mMeshes[a]) << "\">" << endstr;
PushTag();
mOutput << startstr << "<bind_material>" << endstr;
PushTag();
mOutput << startstr << "<technique_common>" << endstr;
PushTag();
mOutput << startstr << "<instance_material symbol=\"theresonlyone\" target=\"#" << materials[mesh->mMaterialIndex].name << "\" />" << endstr;
mOutput << startstr << "<bind_material>" << endstr;
PushTag();
mOutput << startstr << "<technique_common>" << endstr;
PushTag();
mOutput << startstr << "<instance_material symbol=\"theresonlyone\" target=\"#" << materials[mesh->mMaterialIndex].name << "\" />" << endstr;
PopTag();
mOutput << startstr << "</technique_common>" << endstr;
PopTag();
mOutput << startstr << "</bind_material>" << endstr;
PopTag();
mOutput << startstr << "</technique_common>" << endstr;
PopTag();
mOutput << startstr << "</bind_material>" << endstr;
PopTag();
mOutput << startstr << "</instance_geometry>" << endstr;
}

View File

@ -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<Material> materials;
std::map<unsigned int, std::string> 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);
};
}

View File

@ -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 );

View File

@ -176,6 +176,8 @@ Exporter :: Exporter()
Exporter :: ~Exporter()
{
FreeBlob();
delete pimpl;
}

View File

@ -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) {

View File

@ -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);

View File

@ -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);

View File

@ -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
{

View File

@ -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<unsigned int> 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<const IfcRepresentation*> 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);
}

View File

@ -1063,7 +1063,7 @@ IfcMatrix4 ProjectOntoPlane(std::vector<IfcVector2>& 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<IfcVector2>& out_contour, const TempMesh
m = mult * m;
// debug code to verify correctness
#ifdef _DEBUG
#ifdef ASSIMP_BUILD_DEBUG
std::vector<IfcVector2> out_contour2;
BOOST_FOREACH(const IfcVector3& x, in_verts) {
const IfcVector3& vv = m * x;

View File

@ -193,7 +193,7 @@ void TempMesh::ComputePolygonNormals(std::vector<IfcVector3>& normals,
temp[cnt++] = v.x;
temp[cnt++] = v.y;
temp[cnt++] = v.z;
#ifdef _DEBUG
#ifdef ASSIMP_BUILD_DEBUG
temp[cnt] = std::numeric_limits<IfcFloat>::quiet_NaN();
#endif
++cnt;

View File

@ -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

View File

@ -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<std::string>::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)
<< "<unknown compiler>"
#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<aiMatrix4x4>(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<std::string>(pimpl->mStringProperties,szName,iErrorReturn);
}
// ------------------------------------------------------------------------------------------------
// Get a configuration property
const aiMatrix4x4 Importer::GetPropertyMatrix(const char* szName,
const aiMatrix4x4& iErrorReturn /*= aiMatrix4x4()*/) const
{
return GetGenericProperty<aiMatrix4x4>(pimpl->mMatrixProperties,szName,iErrorReturn);
}
// ------------------------------------------------------------------------------------------------
// Get the memory requirements of a single node
inline void AddNodeWeight(unsigned int& iScene,const aiNode* pcNode)

View File

@ -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<KeyType, int> IntPropertyMap;
typedef std::map<KeyType, float> FloatPropertyMap;
typedef std::map<KeyType, std::string> StringPropertyMap;
typedef std::map<KeyType, aiMatrix4x4> 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

View File

@ -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;
}

View File

@ -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 <stdexcept>
#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 <stdexcept>
#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 <size_t N>
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 <size_t N>
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

View File

@ -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,

View File

@ -115,7 +115,7 @@ AI_FORCE_INLINE bool SkipSpaces( const char_t** inout)
}
// ---------------------------------------------------------------------------------
template <class char_t>
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 <class char_t>
inline bool SkipLine( const char_t** inout)
AI_FORCE_INLINE bool SkipLine( const char_t** inout)
{
return SkipLine<char_t>(*inout,inout);
}
// ---------------------------------------------------------------------------------
template <class char_t>
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 <class char_t>
inline bool SkipSpacesAndLineEnd( const char_t** inout)
AI_FORCE_INLINE bool SkipSpacesAndLineEnd( const char_t** inout)
{
return SkipSpacesAndLineEnd<char_t>(*inout,inout);
}
// ---------------------------------------------------------------------------------
template <class char_t>
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;

View File

@ -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

View File

@ -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<aiMesh*>& out, aiMesh** in
ntz->mBones = reinterpret_cast<aiBone**> (&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);

View File

@ -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

View File

@ -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 + "." );

View File

@ -46,23 +46,144 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <algorithm>
#include <cassert>
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<std::string, ZipFile*>::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<std::string, ZipFile*>::const_iterator it = m_ArchiveMap.find(rFile);
if(it != m_ArchiveMap.end()) {
exist = true;
}
}
std::string rFile( pFile );
std::vector<std::string>::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<std::string>::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<std::string, ZipFile*>::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<std::string, IOStream*>::iterator it;
for ( it = m_ArchiveMap.begin(); it != m_ArchiveMap.end(); ++it )
{
if ( (*it).second == pFile )
{
ZipFile *pZipFile = reinterpret_cast<ZipFile*>( (*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<std::string> &rFileList )
{
rFileList = m_FileList;
void Q3BSPZipArchive::getFileList(std::vector<std::string> &rFileList) {
rFileList.clear();
for(std::map<std::string, ZipFile*>::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<std::map<std::string, ZipFile*>::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;
}
// ------------------------------------------------------------------------------------------------

View File

@ -48,10 +48,35 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <map>
#include <cassert>
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<std::string> &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<std::string> &rFileList);
private:
bool mapArchive();
private:
unzFile m_ZipFileHandle;
std::map<std::string, ZipFile*> m_ArchiveMap;
private:
unzFile m_ZipFileHandle;
std::map<std::string, IOStream*> m_ArchiveMap;
std::vector<std::string> m_FileList;
bool m_bDirty;
};
// ------------------------------------------------------------------------------------------------

View File

@ -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;
}

View File

@ -192,19 +192,19 @@ namespace STEP {
}
// utilities to deal with SELECT entities, which currently lack automatic
// conversion support.
template <typename T>
const T& ResolveSelect(const DB& db) const {
return Couple<T>(db).MustGetObject(To<EXPRESS::ENTITY>())->template To<T>();
}
template <typename T>
const T* ResolveSelectPtr(const DB& db) const {
const EXPRESS::ENTITY* e = ToPtr<EXPRESS::ENTITY>();
return e?Couple<T>(db).MustGetObject(*e)->template ToPtr<T>():(const T*)0;
}
public:
// conversion support.
template <typename T>
const T& ResolveSelect(const DB& db) const {
return Couple<T>(db).MustGetObject(To<EXPRESS::ENTITY>())->template To<T>();
}
template <typename T>
const T* ResolveSelectPtr(const DB& db) const {
const EXPRESS::ENTITY* e = ToPtr<EXPRESS::ENTITY>();
return e?Couple<T>(db).MustGetObject(*e)->template ToPtr<T>():(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,

View File

@ -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<char> );
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<const EXPRESS::DataType> EXPRESS::DataType::Parse(const char*&
{
const char* cur = inout;
SkipSpaces(&cur);
if (*cur == ',' || IsSpaceOrNewLine(*cur)) {
throw STEP::SyntaxError("unexpected token, expected parameter",line);
}

View File

@ -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<IOStream> 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 <size_t N, size_t N2> 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

View File

@ -880,6 +880,59 @@ void SceneCombiner::MergeMeshes(aiMesh** _out,unsigned int /*flags*/,
delete *it;
}
// ------------------------------------------------------------------------------------------------
void SceneCombiner::MergeMaterials(aiMaterial** dest,
std::vector<aiMaterial*>::const_iterator begin,
std::vector<aiMaterial*>::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<aiMaterial*>::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<aiMaterial*>::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 <typename Type>
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];

View File

@ -248,6 +248,20 @@ public:
static void MergeBones(aiMesh* out,std::vector<aiMesh*>::const_iterator it,
std::vector<aiMesh*>::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<aiMaterial*>::const_iterator begin,
std::vector<aiMaterial*>::const_iterator end);
// -------------------------------------------------------------------
/** Builds a list of uniquely named bones in a mesh list

View File

@ -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);

View File

@ -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;

View File

@ -329,7 +329,7 @@ unsigned int SpatialSort::GenerateMappingTable(std::vector<unsigned int>& 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) {

View File

@ -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;

View File

@ -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));

View File

@ -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 <typename Real>
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<Real>( 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<Real>(10.0f), exp);
f *= pow(static_cast<Real>(10.0), exp);
}
if (inv) {

View File

@ -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);
}

View File

@ -215,7 +215,7 @@ private:
{
char_type* start = P;
// more forward until '<' found
// move forward until '<' found
while(*P != L'<' && *P)
++P;

View File

@ -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 <windows.h>
/* 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 <limits.h>
# 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 <sys/types.h> /* for off_t */
# endif
#endif
#if defined(STDC) || defined(Z_HAVE_STDARG_H)
# ifndef Z_SOLO
# include <stdarg.h> /* for va_list */
# endif
#endif
#ifdef _WIN32
# ifndef Z_SOLO
# include <stddef.h> /* 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 <unistd.h> /* for SEEK_*, off_t, and _LFS64_LARGEFILE */
# ifdef VMS
# include <unixio.h> /* 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 */

View File

@ -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. */

View File

@ -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:

View File

@ -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

View File

@ -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() {

View File

@ -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:
// ----------------------------------------------------------------------

View File

@ -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 () {

View File

@ -3,7 +3,7 @@
#ifndef AI_DEBUG_H_INC
#define AI_DEBUG_H_INC
#ifdef _DEBUG
#ifdef ASSIMP_BUILD_DEBUG
# include <assert.h>
# define ai_assert(expression) assert(expression)
#else

View File

@ -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.

View File

@ -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;

View File

@ -94,6 +94,23 @@ AI_FORCE_INLINE bool aiColor4t<TReal>::operator!= (const aiColor4t<TReal>& other
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
AI_FORCE_INLINE bool aiColor4t<TReal>::operator< (const aiColor4t<TReal>& 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 <typename TReal>
AI_FORCE_INLINE aiColor4t<TReal> operator + (const aiColor4t<TReal>& v1, const aiColor4t<TReal>& v2) {
return aiColor4t<TReal>( v1.r + v2.r, v1.g + v2.g, v1.b + v2.b, v1.a + v2.a);
}

View File

@ -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.

View File

@ -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

View File

@ -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
*

View File

@ -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);
}
// ---------------------------------------------------------------------------

View File

@ -90,8 +90,10 @@ public:
const TReal* operator[] (unsigned int p_iIndex) const;
// comparison operators
bool operator== (const aiMatrix4x4t<TReal> m) const;
bool operator!= (const aiMatrix4x4t<TReal> m) const;
bool operator== (const aiMatrix4x4t<TReal>& m) const;
bool operator!= (const aiMatrix4x4t<TReal>& m) const;
bool Equal(const aiMatrix4x4t<TReal>& m, TReal epsilon = 1e-6) const;
template <typename TOther>
operator aiMatrix3x3t<TOther> () const;

View File

@ -50,6 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "matrix4x4.h"
#include <algorithm>
#include <cmath>
#include <limits>
// ------------------------------------------------------------------------------------------------
@ -113,7 +114,7 @@ inline const TReal* aiMatrix3x3t<TReal>::operator[] (unsigned int p_iIndex) cons
// ------------------------------------------------------------------------------------------------
template <typename TReal>
inline bool aiMatrix3x3t<TReal>::operator== (const aiMatrix4x4t<TReal> m) const
inline bool aiMatrix3x3t<TReal>::operator== (const aiMatrix4x4t<TReal>& 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<TReal>::operator== (const aiMatrix4x4t<TReal> m) const
// ------------------------------------------------------------------------------------------------
template <typename TReal>
inline bool aiMatrix3x3t<TReal>::operator!= (const aiMatrix4x4t<TReal> m) const
inline bool aiMatrix3x3t<TReal>::operator!= (const aiMatrix4x4t<TReal>& m) const
{
return !(*this == m);
}
// ---------------------------------------------------------------------------
template<typename TReal>
inline bool aiMatrix3x3t<TReal>::Equal(const aiMatrix4x4t<TReal>& 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 <typename TReal>
inline aiMatrix3x3t<TReal>& aiMatrix3x3t<TReal>::Transpose()

View File

@ -78,6 +78,14 @@ public:
/** construction from 3x3 matrix, remaining elements are set to identity */
explicit aiMatrix4x4t( const aiMatrix3x3t<TReal>& 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<TReal>& scaling, aiQuaterniont<TReal>& rotation,
aiVector3t<TReal>& 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);

View File

@ -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 <algorithm>
#include <limits>
#include <limits>
#ifdef __cplusplus
# include <cmath>
#else
# include <math.h>
#endif
#endif
// ----------------------------------------------------------------------------------------
template <typename TReal>
aiMatrix4x4t<TReal> ::aiMatrix4x4t () :
a1(1.0f), a2(), a3(), a4(),
b1(), b2(1.0f), b3(), b4(),
aiMatrix4x4t<TReal> ::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 <typename TReal>
aiMatrix4x4t<TReal> ::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<TReal>::aiMatrix4x4t (const aiMatrix3x3t<TReal>& m)
d1 = static_cast<TReal>(0.0); d2 = static_cast<TReal>(0.0); d3 = static_cast<TReal>(0.0); d4 = static_cast<TReal>(1.0);
}
// ----------------------------------------------------------------------------------------
template <typename TReal>
inline aiMatrix4x4t<TReal>::aiMatrix4x4t (aiVector3t<TReal>& scaling, aiQuaterniont<TReal>& rotation, aiVector3t<TReal>& position)
{
// build a 3x3 rotation matrix
aiMatrix3x3t<TReal> 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<TReal>(0.0);
d2 = static_cast<TReal>(0.0);
d3 = static_cast<TReal>(0.0);
d4 = static_cast<TReal>(1.0);
}
// ----------------------------------------------------------------------------------------
template <typename TReal>
inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::operator *= (const aiMatrix4x4t<TReal>& m)
@ -160,10 +188,10 @@ inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::Transpose()
template <typename TReal>
inline TReal aiMatrix4x4t<TReal>::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<TReal>& aiMatrix4x4t<TReal>::Inverse()
{
// Compute the reciprocal determinant
const TReal det = Determinant();
if(det == static_cast<TReal>(0.0))
if(det == static_cast<TReal>(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<TReal>& aiMatrix4x4t<TReal>::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<TReal>::operator[](unsigned int p_iIndex) const
// ----------------------------------------------------------------------------------------
template <typename TReal>
inline bool aiMatrix4x4t<TReal>::operator== (const aiMatrix4x4t<TReal> m) const
inline bool aiMatrix4x4t<TReal>::operator== (const aiMatrix4x4t<TReal>& 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<TReal>::operator== (const aiMatrix4x4t<TReal> m) const
// ----------------------------------------------------------------------------------------
template <typename TReal>
inline bool aiMatrix4x4t<TReal>::operator!= (const aiMatrix4x4t<TReal> m) const
inline bool aiMatrix4x4t<TReal>::operator!= (const aiMatrix4x4t<TReal>& m) const
{
return !(*this == m);
}
// ---------------------------------------------------------------------------
template<typename TReal>
inline bool aiMatrix4x4t<TReal>::Equal(const aiMatrix4x4t<TReal>& 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 <typename TReal>
inline void aiMatrix4x4t<TReal>::Decompose (aiVector3t<TReal>& scaling, aiQuaterniont<TReal>& rotation,
@ -373,9 +423,9 @@ inline bool aiMatrix4x4t<TReal>::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<TReal>& aiMatrix4x4t<TReal>::Scaling( const aiVector3t<TReal
*/
// ----------------------------------------------------------------------------------------
template <typename TReal>
inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::FromToMatrix(const aiVector3t<TReal>& from,
inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::FromToMatrix(const aiVector3t<TReal>& from,
const aiVector3t<TReal>& to, aiMatrix4x4t<TReal>& mtx)
{
{
aiMatrix3x3t<TReal> m3;
aiMatrix3x3t<TReal>::FromToMatrix(from,to,m3);
mtx = aiMatrix4x4t<TReal>(m3);

View File

@ -620,7 +620,7 @@ struct aiMesh
, mBitangents( NULL )
, mFaces( NULL )
, mNumBones( 0 )
, mBones( 0 )
, mBones( NULL )
, mMaterialIndex( 0 )
, mNumAnimMeshes( 0 )
, mAnimMeshes( NULL )

View File

@ -64,7 +64,9 @@ enum aiMetadataType
AI_AISTRING = 4,
AI_AIVECTOR3D = 5,
#ifndef SWIG
FORCE_32BIT = INT_MAX
#endif
};

View File

@ -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 */

View File

@ -48,6 +48,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifdef __cplusplus
#include "quaternion.h"
#include <cmath>
// ---------------------------------------------------------------------------
template<typename TReal>
bool aiQuaterniont<TReal>::operator== (const aiQuaterniont& o) const
@ -62,7 +64,15 @@ bool aiQuaterniont<TReal>::operator!= (const aiQuaterniont& o) const
return !(*this == o);
}
// ---------------------------------------------------------------------------
template<typename TReal>
inline bool aiQuaterniont<TReal>::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

View File

@ -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.

View File

@ -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

View File

@ -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 <cmath>
#else
# include <math.h>
#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);

View File

@ -48,6 +48,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifdef __cplusplus
#include "vector2.h"
#include <cmath>
// ------------------------------------------------------------------------------------------------
template <typename TReal>
template <typename TOther>
@ -131,6 +133,14 @@ bool aiVector2t<TReal>::operator!= (const aiVector2t& other) const {
return x != other.x || y != other.y;
}
// ---------------------------------------------------------------------------
template<typename TReal>
bool aiVector2t<TReal>::Equal(const aiVector2t& other, TReal epsilon) const {
return
std::abs(x - other.x) <= epsilon &&
std::abs(y - other.y) <= epsilon;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
aiVector2t<TReal>& aiVector2t<TReal>::operator= (TReal f) {

View File

@ -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 <cmath>
#else
# include <math.h>
#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 <typename TOther>
operator aiVector3t<TOther> () const;

View File

@ -48,6 +48,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifdef __cplusplus
#include "vector3.h"
#include <cmath>
// ------------------------------------------------------------------------------------------------
/** Transformation of a vector by a 3x3 matrix */
template <typename TReal>
@ -147,6 +149,14 @@ template <typename TReal>
AI_FORCE_INLINE bool aiVector3t<TReal>::operator!= (const aiVector3t<TReal>& other) const {
return x != other.x || y != other.y || z != other.z;
}
// ---------------------------------------------------------------------------
template<typename TReal>
AI_FORCE_INLINE bool aiVector3t<TReal>::Equal(const aiVector3t<TReal>& other, TReal epsilon) const {
return
std::abs(x - other.x) <= epsilon &&
std::abs(y - other.y) <= epsilon &&
std::abs(z - other.z) <= epsilon;
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
AI_FORCE_INLINE const aiVector3t<TReal> aiVector3t<TReal>::SymMul(const aiVector3t<TReal>& o) {

View File

@ -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 <verb> <parameters>\n\n"

View File

@ -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;