summaryrefslogtreecommitdiffstats
path: root/src/3rdparty
diff options
context:
space:
mode:
authorPaul Lemire <paul.lemire@kdab.com>2014-06-27 09:31:11 +0200
committerPaul Lemire <paul.lemire@kdab.com>2014-07-17 10:14:00 +0200
commit09687cfaade1e3baa693f02861722ea860f3c716 (patch)
tree4d1084ee95ec45e880739ddf709ae32fe73d3caa /src/3rdparty
parent22829fba69a36e447a14dcd59149164d482b3fe3 (diff)
Upgrade to Assimp 3.1.1
https://github.com/assimp/assimp/releases/tag/v3.1.1 This commit imports assimp 3.1.1, including CHANGES, CREDITS, LICENSE, README, Readme.md, and code, contrib, include directories. contrib/zlib, contrib/cppunit-1.12.1/, contrib/cppunit_note.txt were excluded in this change. assimp.pri was also updated. revision.h was generated from revision.h.in. Change-Id: I7c0597eae9eee7f06a1170968b5fef6fd46b6f0d Reviewed-by: Liang Qi <liang.qi@digia.com> Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src/3rdparty')
-rw-r--r--src/3rdparty/assimp/CREDITS13
-rw-r--r--src/3rdparty/assimp/Readme.md6
-rw-r--r--src/3rdparty/assimp/assimp.pri37
-rw-r--r--src/3rdparty/assimp/code/AssimpPCH.cpp2
-rw-r--r--src/3rdparty/assimp/code/AssimpPCH.h2
-rw-r--r--src/3rdparty/assimp/code/BlenderLoader.cpp4
-rw-r--r--src/3rdparty/assimp/code/BlenderModifier.cpp9
-rw-r--r--src/3rdparty/assimp/code/BoostWorkaround/boost/shared_array.hpp2
-rw-r--r--src/3rdparty/assimp/code/BoostWorkaround/boost/shared_ptr.hpp4
-rw-r--r--src/3rdparty/assimp/code/BoostWorkaround/boost/tuple/tuple.hpp2
-rw-r--r--src/3rdparty/assimp/code/CMakeLists.txt10
-rw-r--r--src/3rdparty/assimp/code/ColladaLoader.cpp3
-rw-r--r--src/3rdparty/assimp/code/FBXAnimation.cpp2
-rw-r--r--src/3rdparty/assimp/code/FBXConverter.cpp195
-rw-r--r--src/3rdparty/assimp/code/FBXImportSettings.h2
-rw-r--r--src/3rdparty/assimp/code/FBXMaterial.cpp2
-rw-r--r--src/3rdparty/assimp/code/FBXParser.cpp24
-rw-r--r--src/3rdparty/assimp/code/FBXProperties.h2
-rw-r--r--src/3rdparty/assimp/code/IFCBoolean.cpp2
-rw-r--r--src/3rdparty/assimp/code/IFCLoader.cpp6
-rw-r--r--src/3rdparty/assimp/code/IFCMaterial.cpp2
-rw-r--r--src/3rdparty/assimp/code/IFCOpenings.cpp4
-rw-r--r--src/3rdparty/assimp/code/IFCProfile.cpp2
-rw-r--r--src/3rdparty/assimp/code/IFCReaderGen.cpp6
-rw-r--r--src/3rdparty/assimp/code/LWOAnimation.cpp2
-rw-r--r--src/3rdparty/assimp/code/M3Importer.cpp371
-rw-r--r--src/3rdparty/assimp/code/M3Importer.h726
-rw-r--r--src/3rdparty/assimp/code/ObjFileImporter.cpp18
-rw-r--r--src/3rdparty/assimp/code/OgreBinarySerializer.cpp1110
-rw-r--r--src/3rdparty/assimp/code/OgreBinarySerializer.h416
-rw-r--r--src/3rdparty/assimp/code/OgreImporter.cpp204
-rw-r--r--src/3rdparty/assimp/code/OgreImporter.h230
-rw-r--r--src/3rdparty/assimp/code/OgreImporter.hpp185
-rw-r--r--src/3rdparty/assimp/code/OgreMaterial.cpp85
-rw-r--r--src/3rdparty/assimp/code/OgreMesh.cpp569
-rw-r--r--src/3rdparty/assimp/code/OgreParsingUtils.h189
-rw-r--r--src/3rdparty/assimp/code/OgreSkeleton.cpp446
-rw-r--r--src/3rdparty/assimp/code/OgreStructs.cpp1193
-rw-r--r--src/3rdparty/assimp/code/OgreStructs.h681
-rw-r--r--src/3rdparty/assimp/code/OgreXmlHelper.hpp88
-rw-r--r--src/3rdparty/assimp/code/OgreXmlSerializer.cpp1003
-rw-r--r--src/3rdparty/assimp/code/OgreXmlSerializer.h116
-rw-r--r--src/3rdparty/assimp/code/Q3BSPFileImporter.cpp10
-rw-r--r--src/3rdparty/assimp/code/Q3BSPZipArchive.cpp10
-rw-r--r--src/3rdparty/assimp/contrib/clipper/clipper.cpp8
-rw-r--r--src/3rdparty/assimp/contrib/unzip/crypt.h3
-rw-r--r--src/3rdparty/assimp/contrib/unzip/ioapi.c45
-rw-r--r--src/3rdparty/assimp/contrib/unzip/unzip.h14
-rw-r--r--src/3rdparty/assimp/include/assimp/Compiler/pstdint.h (renamed from src/3rdparty/assimp/code/pstdint.h)0
-rw-r--r--src/3rdparty/assimp/include/assimp/matrix4x4.h4
-rw-r--r--src/3rdparty/assimp/include/assimp/matrix4x4.inl2
-rw-r--r--src/3rdparty/assimp/include/assimp/metadata.h2
-rw-r--r--src/3rdparty/assimp/include/assimp/quaternion.h2
-rw-r--r--src/3rdparty/assimp/include/assimp/vector3.h1
-rw-r--r--src/3rdparty/assimp/include/assimp/vector3.inl5
-rw-r--r--src/3rdparty/assimp/revision.h3
56 files changed, 5025 insertions, 3059 deletions
diff --git a/src/3rdparty/assimp/CREDITS b/src/3rdparty/assimp/CREDITS
index 33f4acce4..070a15431 100644
--- a/src/3rdparty/assimp/CREDITS
+++ b/src/3rdparty/assimp/CREDITS
@@ -3,8 +3,8 @@ Open Asset Import Library (Assimp)
Developers and Contributors
===============================================================
-The following is the list of all constributors.
-Thanks for your help!
+The following is a non-exhaustive list of all constributors over the years.
+If you think your name should be listed here, drop us a line and we'll add you.
- Alexander Gessler,
3DS-, BLEND-, ASE-, DXF-, HMP-, MDL-, MD2-, MD3-, MD5-, MDC-, NFF-, PLY-, STL-, RAW-, OFF-, MS3D-, Q3D- and LWO-Loader, Assimp-Viewer, assimp-cmd, -noboost, Website (Admin and Design).
@@ -41,7 +41,7 @@ Submitted patches to make Assimp compile with GCC-4, a makefile and the xcode3 w
- Andreas Nagel
First Assimp testing & verification under Windows Vista 64 Bit.
-- Marius Schröder
+- Marius Schr�der
Allowed us to use many of his models for screenshots and testing.
- Christian Schubert
@@ -92,7 +92,7 @@ Contributed the 'SimpleTexturedOpenGl' sample.
- Matthias Fauconneau
Contributed a fix for the Q3-BSP loader.
-- Jørgen P. Tjernø
+- J�rgen P. Tjern�
Contributed updated and improved xcode workspaces
- drparallax
@@ -137,7 +137,7 @@ GCC/Linux fixes for the SimpleOpenGL sample.
- Brian Miller
Bugfix for a compiler fix for iOS on arm.
-- Séverin Lemaignan
+- S�verin Lemaignan
Rewrite of PyAssimp, distutils and Python3 support
- albert-wang
@@ -145,3 +145,6 @@ Bugfixes for the collada parser
- Ya ping Jin
Bugfixes for uv-tanget calculation.
+
+- Jonne Nauha
+Ogre Binary format support
diff --git a/src/3rdparty/assimp/Readme.md b/src/3rdparty/assimp/Readme.md
index 380e4386f..214417798 100644
--- a/src/3rdparty/assimp/Readme.md
+++ b/src/3rdparty/assimp/Readme.md
@@ -1,9 +1,7 @@
Open Asset Import Library (assimp)
========
-Open Asset Import Library is a Open Source library designed to load various __3d file formats and convert them into a single, in-memory format__. It supports more than __30 file formats__ for import and a growing selection of file formats for export. Additionally, assimp features various __post processing tools__ to refine the imported data: _normals and tangent space generation, triangulation, vertex cache locality optimization, removal of degenerate primitives and duplicate vertices, sorting by primitive type, merging of redundant materials_ and many more.
-
-Its short name under which it is commonly known is __assimp__.
+Open Asset Import Library is a Open Source library designed to load various __3d file formats and convert them into a shared, in-memory format__. It supports more than __30 file formats__ for import and a growing selection of file formats for export. Additionally, assimp features various __post processing tools__ to refine the imported data: _normals and tangent space generation, triangulation, vertex cache locality optimization, removal of degenerate primitives and duplicate vertices, sorting by primitive type, merging of redundant materials_ and many more.
This is the development trunk of assimp containing the latest features and bugfixes. For productive use though, we recommend one of the stable releases available from [assimp.sf.net](http://assimp.sf.net) or from *nix package repositories. According to [Travis-CI] (https://travis-ci.org/), the current build status of the trunk is [![Build Status](https://travis-ci.org/assimp/assimp.png)](https://travis-ci.org/assimp/assimp)
@@ -43,6 +41,7 @@ The library provides importers for a lot of file formats, including:
- BVH
- B3D
- NDO
+- Ogre Binary
- Ogre XML
- Q3D
@@ -56,6 +55,7 @@ Exporters include:
- STL
- OBJ
- PLY
+- JSON (for WebGl, via https://github.com/acgessler/assimp2json)
See [the full list here](http://assimp.sourceforge.net/main_features_formats.html).
diff --git a/src/3rdparty/assimp/assimp.pri b/src/3rdparty/assimp/assimp.pri
index bf7fc2fdc..634a8e611 100644
--- a/src/3rdparty/assimp/assimp.pri
+++ b/src/3rdparty/assimp/assimp.pri
@@ -117,7 +117,6 @@ HEADERS += revision.h \
code/LWOFileData.h \
code/LWOLoader.h \
code/LWSLoader.h \
- code/M3Importer.h \
code/MakeVerboseFormat.h \
code/MaterialSystem.h \
code/MD2FileData.h \
@@ -145,8 +144,6 @@ HEADERS += revision.h \
code/ObjFileParser.h \
code/ObjTools.h \
code/OFFLoader.h \
- code/OgreImporter.hpp \
- code/OgreXmlHelper.hpp \
code/OptimizeGraph.h \
code/OptimizeMeshes.h \
code/ParsingUtils.h \
@@ -157,7 +154,6 @@ HEADERS += revision.h \
code/PretransformVertices.h \
code/ProcessHelper.h \
code/Profiler.h \
- code/pstdint.h \
code/Q3BSPFileData.h \
code/Q3BSPFileImporter.h \
code/Q3BSPFileParser.h \
@@ -246,6 +242,17 @@ HEADERS += revision.h \
include/assimp/vector2.h \
include/assimp/vector3.h \
include/assimp/version.h \
+ include/assimp/vector2.inl \
+ include/assimp/vector3.inl \
+ include/assimp/color4.inl \
+ include/assimp/quaternion.inl \
+ include/assimp/matrix3x3.inl \
+ include/assimp/matrix4x4.inl \
+ include/assimp/material.inl \
+ include/assimp/metadata.h \
+ include/assimp/Compiler/poppack1.h \
+ include/assimp/Compiler/pushpack1.h \
+ include/assimp/Compiler/pstdint.h \
code/BoostWorkaround/boost/foreach.hpp \
code/BoostWorkaround/boost/format.hpp \
code/BoostWorkaround/boost/lexical_cast.hpp \
@@ -259,8 +266,6 @@ HEADERS += revision.h \
code/BoostWorkaround/boost/static_assert.hpp \
code/BoostWorkaround/boost/timer.hpp \
contrib/poly2tri/poly2tri/poly2tri.h \
- include/assimp/Compiler/poppack1.h \
- include/assimp/Compiler/pushpack1.h \
code/BoostWorkaround/boost/math/common_factor_rt.hpp \
code/BoostWorkaround/boost/tuple/tuple.hpp \
contrib/poly2tri/poly2tri/common/shapes.h \
@@ -269,13 +274,6 @@ HEADERS += revision.h \
contrib/poly2tri/poly2tri/sweep/cdt.h \
contrib/poly2tri/poly2tri/sweep/sweep.h \
contrib/poly2tri/poly2tri/sweep/sweep_context.h \
- include/assimp/vector2.inl \
- include/assimp/vector3.inl \
- include/assimp/color4.inl \
- include/assimp/quaternion.inl \
- include/assimp/matrix3x3.inl \
- include/assimp/matrix4x4.inl \
- include/assimp/material.inl \
code/SmoothingGroups.inl \
code/BlenderDNA.inl \
code/FBXConverter.h \
@@ -291,7 +289,9 @@ HEADERS += revision.h \
code/OgreParsingUtils.h \
code/FBXCompileConfig.h \
code/STEPFileEncoding.h \
- include/assimp/metadata.h
+ code/OgreBinarySerializer.h \
+ code/OgreStructs.h \
+ code/OgreXmlSerializer.h
SOURCES += code/3DSConverter.cpp \
code/3DSLoader.cpp \
@@ -353,7 +353,6 @@ SOURCES += code/3DSConverter.cpp \
code/LWOLoader.cpp \
code/LWOMaterial.cpp \
code/LWSLoader.cpp \
- code/M3Importer.cpp \
code/MakeVerboseFormat.cpp \
code/MaterialSystem.cpp \
code/MD2Loader.cpp \
@@ -373,8 +372,6 @@ SOURCES += code/3DSConverter.cpp \
code/OFFLoader.cpp \
code/OgreImporter.cpp \
code/OgreMaterial.cpp \
- code/OgreMesh.cpp \
- code/OgreSkeleton.cpp \
code/OptimizeGraph.cpp \
code/OptimizeMeshes.cpp \
code/PlyExporter.cpp \
@@ -442,6 +439,10 @@ SOURCES += code/3DSConverter.cpp \
code/IFCBoolean.cpp \
code/IFCOpenings.cpp \
code/FBXConverter.cpp \
- code/STEPFileEncoding.cpp
+ code/STEPFileEncoding.cpp \
+ code/OgreBinarySerializer.cpp \
+ code/OgreStructs.cpp \
+ code/OgreXmlSerializer.cpp
+
diff --git a/src/3rdparty/assimp/code/AssimpPCH.cpp b/src/3rdparty/assimp/code/AssimpPCH.cpp
index 59e2620f8..1f61feb2c 100644
--- a/src/3rdparty/assimp/code/AssimpPCH.cpp
+++ b/src/3rdparty/assimp/code/AssimpPCH.cpp
@@ -63,7 +63,7 @@ ASSIMP_API unsigned int aiGetCompileFlags () {
}
// include current build revision, which is even updated from time to time -- :-)
-#include "../revision.h"
+#include "revision.h"
// ------------------------------------------------------------------------------------------------
ASSIMP_API unsigned int aiGetVersionRevision ()
diff --git a/src/3rdparty/assimp/code/AssimpPCH.h b/src/3rdparty/assimp/code/AssimpPCH.h
index 2c7a6bee4..624ecc39b 100644
--- a/src/3rdparty/assimp/code/AssimpPCH.h
+++ b/src/3rdparty/assimp/code/AssimpPCH.h
@@ -56,7 +56,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Include our stdint.h replacement header for MSVC, take the global header for gcc/mingw
#if defined( _MSC_VER) && (_MSC_VER < 1600)
-# include "pstdint.h"
+# include "../include/assimp/Compiler/pstdint.h"
#else
# include <stdint.h>
#endif
diff --git a/src/3rdparty/assimp/code/BlenderLoader.cpp b/src/3rdparty/assimp/code/BlenderLoader.cpp
index 0b5c71333..8f9b85b26 100644
--- a/src/3rdparty/assimp/code/BlenderLoader.cpp
+++ b/src/3rdparty/assimp/code/BlenderLoader.cpp
@@ -999,7 +999,7 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
}
// ------------------------------------------------------------------------------------------------
-aiCamera* BlenderImporter::ConvertCamera(const Scene& /*in*/, const Object* obj, const Camera* /*camera*/, ConversionData& /*conv_data*/)
+aiCamera* BlenderImporter::ConvertCamera(const Scene& /*in*/, const Object* obj, const Camera* camera, ConversionData& /*conv_data*/)
{
ScopeGuard<aiCamera> out(new aiCamera());
out->mName = obj->id.name+2;
@@ -1010,7 +1010,7 @@ aiCamera* BlenderImporter::ConvertCamera(const Scene& /*in*/, const Object* obj,
}
// ------------------------------------------------------------------------------------------------
-aiLight* BlenderImporter::ConvertLight(const Scene& /*in*/, const Object* obj, const Lamp* lamp, ConversionData& /*conv_data*/)
+aiLight* BlenderImporter::ConvertLight(const Scene& in, const Object* obj, const Lamp* lamp, ConversionData& conv_data)
{
ScopeGuard<aiLight> out(new aiLight());
out->mName = obj->id.name+2;
diff --git a/src/3rdparty/assimp/code/BlenderModifier.cpp b/src/3rdparty/assimp/code/BlenderModifier.cpp
index afb6181b0..6ed31271c 100644
--- a/src/3rdparty/assimp/code/BlenderModifier.cpp
+++ b/src/3rdparty/assimp/code/BlenderModifier.cpp
@@ -248,6 +248,15 @@ void BlenderModifier_Mirror :: DoIt(aiNode& out, ConversionData& conv_data, co
}
}
+ // Only reverse the winding order if an odd number of axes were mirrored.
+ if (xs * ys * zs < 0) {
+ for( unsigned int i = 0; i < mesh->mNumFaces; i++) {
+ aiFace& face = mesh->mFaces[i];
+ for( unsigned int fi = 0; fi < face.mNumIndices / 2; ++fi)
+ std::swap( face.mIndices[fi], face.mIndices[face.mNumIndices - 1 - fi]);
+ }
+ }
+
conv_data.meshes->push_back(mesh);
}
unsigned int* nind = new unsigned int[out.mNumMeshes*2];
diff --git a/src/3rdparty/assimp/code/BoostWorkaround/boost/shared_array.hpp b/src/3rdparty/assimp/code/BoostWorkaround/boost/shared_array.hpp
index 872d57665..9847d9f82 100644
--- a/src/3rdparty/assimp/code/BoostWorkaround/boost/shared_array.hpp
+++ b/src/3rdparty/assimp/code/BoostWorkaround/boost/shared_array.hpp
@@ -2,7 +2,7 @@
#ifndef INCLUDED_AI_BOOST_SHARED_ARRAY
#define INCLUDED_AI_BOOST_SHARED_ARRAY
-#ifndef BOOST_SCOPED_ARRAY_HPP_INCLUDED
+#ifndef BOOST_SHARED_ARRAY_HPP_INCLUDED
// ------------------------------
// Internal stub
diff --git a/src/3rdparty/assimp/code/BoostWorkaround/boost/shared_ptr.hpp b/src/3rdparty/assimp/code/BoostWorkaround/boost/shared_ptr.hpp
index bba9d0674..fe9dcd8be 100644
--- a/src/3rdparty/assimp/code/BoostWorkaround/boost/shared_ptr.hpp
+++ b/src/3rdparty/assimp/code/BoostWorkaround/boost/shared_ptr.hpp
@@ -2,7 +2,7 @@
#ifndef INCLUDED_AI_BOOST_SHARED_PTR
#define INCLUDED_AI_BOOST_SHARED_PTR
-#ifndef BOOST_SCOPED_PTR_HPP_INCLUDED
+#ifndef BOOST_SHARED_PTR_HPP_INCLUDED
// ------------------------------
// Internal stub
@@ -254,4 +254,4 @@ inline shared_ptr<T> const_pointer_cast( shared_ptr<U> ptr)
#else
# error "shared_ptr.h was already included"
#endif
-#endif // INCLUDED_AI_BOOST_SCOPED_PTR
+#endif // INCLUDED_AI_BOOST_SHARED_PTR
diff --git a/src/3rdparty/assimp/code/BoostWorkaround/boost/tuple/tuple.hpp b/src/3rdparty/assimp/code/BoostWorkaround/boost/tuple/tuple.hpp
index 7820aa60a..0ff61d9c3 100644
--- a/src/3rdparty/assimp/code/BoostWorkaround/boost/tuple/tuple.hpp
+++ b/src/3rdparty/assimp/code/BoostWorkaround/boost/tuple/tuple.hpp
@@ -100,7 +100,7 @@ namespace boost {
};
// dummy
- list_elem& operator = (const list_elem& /*other*/) {
+ list_elem& operator = (const list_elem& other) {
return *this;
}
diff --git a/src/3rdparty/assimp/code/CMakeLists.txt b/src/3rdparty/assimp/code/CMakeLists.txt
index 994904fdc..796711316 100644
--- a/src/3rdparty/assimp/code/CMakeLists.txt
+++ b/src/3rdparty/assimp/code/CMakeLists.txt
@@ -10,7 +10,7 @@ SET( HEADER_PATH ../include/assimp )
SET( COMPILER_HEADERS
${HEADER_PATH}/Compiler/pushpack1.h
${HEADER_PATH}/Compiler/poppack1.h
- pstdint.h
+ ${HEADER_PATH}/Compiler/pstdint.h
)
SOURCE_GROUP( Compiler FILES ${COMPILER_HEADERS})
@@ -322,11 +322,15 @@ SOURCE_GROUP( Obj FILES ${Obj_SRCS})
SET( Ogre_SRCS
OgreImporter.h
+ OgreStructs.h
OgreParsingUtils.h
+ OgreBinarySerializer.h
+ OgreXmlSerializer.h
OgreImporter.cpp
+ OgreStructs.cpp
+ OgreBinarySerializer.cpp
+ OgreXmlSerializer.cpp
OgreMaterial.cpp
- OgreMesh.cpp
- OgreSkeleton.cpp
)
SOURCE_GROUP( Ogre FILES ${Ogre_SRCS})
diff --git a/src/3rdparty/assimp/code/ColladaLoader.cpp b/src/3rdparty/assimp/code/ColladaLoader.cpp
index 86406aad9..058baf9c9 100644
--- a/src/3rdparty/assimp/code/ColladaLoader.cpp
+++ b/src/3rdparty/assimp/code/ColladaLoader.cpp
@@ -133,6 +133,7 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
mLights.clear();
mCameras.clear();
mTextures.clear();
+ mAnims.clear();
// parse the input file
ColladaParser parser( pIOHandler, pFile);
@@ -904,6 +905,8 @@ void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pPars
pScene->mAnimations = new aiAnimation*[mAnims.size()];
std::copy( mAnims.begin(), mAnims.end(), pScene->mAnimations);
}
+
+ mAnims.clear();
}
// ------------------------------------------------------------------------------------------------
diff --git a/src/3rdparty/assimp/code/FBXAnimation.cpp b/src/3rdparty/assimp/code/FBXAnimation.cpp
index 3bf60acd4..ccf1d82f4 100644
--- a/src/3rdparty/assimp/code/FBXAnimation.cpp
+++ b/src/3rdparty/assimp/code/FBXAnimation.cpp
@@ -59,7 +59,7 @@ namespace FBX {
using namespace Util;
// ------------------------------------------------------------------------------------------------
-AnimationCurve::AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& /*doc*/)
+AnimationCurve::AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& doc)
: Object(id, element, name)
{
const Scope& sc = GetRequiredScope(element);
diff --git a/src/3rdparty/assimp/code/FBXConverter.cpp b/src/3rdparty/assimp/code/FBXConverter.cpp
index 82f552576..89854fc8e 100644
--- a/src/3rdparty/assimp/code/FBXConverter.cpp
+++ b/src/3rdparty/assimp/code/FBXConverter.cpp
@@ -121,7 +121,7 @@ public:
if(mat) {
if (materials_converted.find(mat) == materials_converted.end()) {
- ConvertMaterial(*mat);
+ ConvertMaterial(*mat, 0);
}
}
}
@@ -783,8 +783,8 @@ private:
data->Set(index++, prop.first, interpreted->Value());
else if (const TypedProperty<float>* interpreted = prop.second->As<TypedProperty<float> >())
data->Set(index++, prop.first, interpreted->Value());
- else if (const TypedProperty<aiString>* interpreted = prop.second->As<TypedProperty<aiString> >())
- data->Set(index++, prop.first, interpreted->Value());
+ else if (const TypedProperty<std::string>* interpreted = prop.second->As<TypedProperty<std::string> >())
+ data->Set(index++, prop.first, aiString(interpreted->Value()));
else if (const TypedProperty<aiVector3D>* interpreted = prop.second->As<TypedProperty<aiVector3D> >())
data->Set(index++, prop.first, interpreted->Value());
else
@@ -1320,7 +1320,7 @@ private:
// ------------------------------------------------------------------------------------------------
- void ConvertCluster(std::vector<aiBone*>& bones, const Model& /*model*/, const Cluster& cl,
+ void ConvertCluster(std::vector<aiBone*>& bones, const Model& model, const Cluster& cl,
std::vector<size_t>& out_indices,
std::vector<size_t>& index_out_indices,
std::vector<size_t>& count_out_indices,
@@ -1363,7 +1363,7 @@ private:
// ------------------------------------------------------------------------------------------------
- void ConvertMaterialForMesh(aiMesh* out, const Model& model, const MeshGeometry& /*geo*/,
+ void ConvertMaterialForMesh(aiMesh* out, const Model& model, const MeshGeometry& geo,
MatIndexArray::value_type materialIndex)
{
// locate source materials for this mesh
@@ -1381,7 +1381,7 @@ private:
return;
}
- out->mMaterialIndex = ConvertMaterial(*mat);
+ out->mMaterialIndex = ConvertMaterial(*mat, &geo);
materials_converted[mat] = out->mMaterialIndex;
}
@@ -1411,7 +1411,7 @@ private:
// ------------------------------------------------------------------------------------------------
// Material -> aiMaterial
- unsigned int ConvertMaterial(const Material& material)
+ unsigned int ConvertMaterial(const Material& material, const MeshGeometry* const mesh)
{
const PropertyTable& props = material.Props();
@@ -1440,8 +1440,8 @@ private:
SetShadingPropertiesCommon(out_mat,props);
// texture assignments
- SetTextureProperties(out_mat,material.Textures());
- SetTextureProperties(out_mat,material.LayeredTextures());
+ SetTextureProperties(out_mat,material.Textures(), mesh);
+ SetTextureProperties(out_mat,material.LayeredTextures(), mesh);
return static_cast<unsigned int>(materials.size() - 1);
}
@@ -1450,7 +1450,7 @@ private:
// ------------------------------------------------------------------------------------------------
void TrySetTextureProperties(aiMaterial* out_mat, const TextureMap& textures,
const std::string& propName,
- aiTextureType target)
+ aiTextureType target, const MeshGeometry* const mesh)
{
TextureMap::const_iterator it = textures.find(propName);
if(it == textures.end()) {
@@ -1495,18 +1495,48 @@ private:
std::find(materials.begin(),materials.end(),out_mat)
));
- uvIndex = -1;
- BOOST_FOREACH(const MeshMap::value_type& v,meshes_converted) {
- const MeshGeometry* const mesh = dynamic_cast<const MeshGeometry*> (v.first);
- if(!mesh) {
- continue;
- }
-
- const MatIndexArray& mats = mesh->GetMaterialIndices();
- if(std::find(mats.begin(),mats.end(),matIndex) == mats.end()) {
- continue;
- }
+ uvIndex = -1;
+ if (!mesh)
+ {
+ BOOST_FOREACH(const MeshMap::value_type& v,meshes_converted) {
+ const MeshGeometry* const mesh = dynamic_cast<const MeshGeometry*> (v.first);
+ if(!mesh) {
+ continue;
+ }
+
+ const MatIndexArray& mats = mesh->GetMaterialIndices();
+ if(std::find(mats.begin(),mats.end(),matIndex) == mats.end()) {
+ continue;
+ }
+
+ int index = -1;
+ for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
+ if(mesh->GetTextureCoords(i).empty()) {
+ break;
+ }
+ const std::string& name = mesh->GetTextureCoordChannelName(i);
+ if(name == uvSet) {
+ index = static_cast<int>(i);
+ break;
+ }
+ }
+ if(index == -1) {
+ FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material");
+ continue;
+ }
+
+ if(uvIndex == -1) {
+ uvIndex = index;
+ }
+ else {
+ FBXImporter::LogWarn("the UV channel named " + uvSet +
+ " appears at different positions in meshes, results will be wrong");
+ }
+ }
+ }
+ else
+ {
int index = -1;
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
if(mesh->GetTextureCoords(i).empty()) {
@@ -1520,17 +1550,12 @@ private:
}
if(index == -1) {
FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material");
- continue;
}
if(uvIndex == -1) {
uvIndex = index;
}
- else {
- FBXImporter::LogWarn("the UV channel named " + uvSet +
- " appears at different positions in meshes, results will be wrong");
- }
- }
+ }
if(uvIndex == -1) {
FBXImporter::LogWarn("failed to resolve UV channel " + uvSet + ", using first UV channel");
@@ -1546,7 +1571,7 @@ private:
// ------------------------------------------------------------------------------------------------
void TrySetTextureProperties(aiMaterial* out_mat, const LayeredTextureMap& layeredTextures,
const std::string& propName,
- aiTextureType target)
+ aiTextureType target, const MeshGeometry* const mesh)
{
LayeredTextureMap::const_iterator it = layeredTextures.find(propName);
if(it == layeredTextures.end()) {
@@ -1590,18 +1615,47 @@ private:
std::find(materials.begin(),materials.end(),out_mat)
));
- uvIndex = -1;
- BOOST_FOREACH(const MeshMap::value_type& v,meshes_converted) {
- const MeshGeometry* const mesh = dynamic_cast<const MeshGeometry*> (v.first);
- if(!mesh) {
- continue;
- }
+ uvIndex = -1;
+ if (!mesh)
+ {
+ BOOST_FOREACH(const MeshMap::value_type& v,meshes_converted) {
+ const MeshGeometry* const mesh = dynamic_cast<const MeshGeometry*> (v.first);
+ if(!mesh) {
+ continue;
+ }
- const MatIndexArray& mats = mesh->GetMaterialIndices();
- if(std::find(mats.begin(),mats.end(),matIndex) == mats.end()) {
- continue;
- }
+ const MatIndexArray& mats = mesh->GetMaterialIndices();
+ if(std::find(mats.begin(),mats.end(),matIndex) == mats.end()) {
+ continue;
+ }
+ int index = -1;
+ for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
+ if(mesh->GetTextureCoords(i).empty()) {
+ break;
+ }
+ const std::string& name = mesh->GetTextureCoordChannelName(i);
+ if(name == uvSet) {
+ index = static_cast<int>(i);
+ break;
+ }
+ }
+ if(index == -1) {
+ FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material");
+ continue;
+ }
+
+ if(uvIndex == -1) {
+ uvIndex = index;
+ }
+ else {
+ FBXImporter::LogWarn("the UV channel named " + uvSet +
+ " appears at different positions in meshes, results will be wrong");
+ }
+ }
+ }
+ else
+ {
int index = -1;
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
if(mesh->GetTextureCoords(i).empty()) {
@@ -1615,17 +1669,12 @@ private:
}
if(index == -1) {
FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material");
- continue;
}
if(uvIndex == -1) {
uvIndex = index;
}
- else {
- FBXImporter::LogWarn("the UV channel named " + uvSet +
- " appears at different positions in meshes, results will be wrong");
- }
- }
+ }
if(uvIndex == -1) {
FBXImporter::LogWarn("failed to resolve UV channel " + uvSet + ", using first UV channel");
@@ -1638,33 +1687,33 @@ private:
}
// ------------------------------------------------------------------------------------------------
- void SetTextureProperties(aiMaterial* out_mat, const TextureMap& textures)
+ void SetTextureProperties(aiMaterial* out_mat, const TextureMap& textures, const MeshGeometry* const mesh)
{
- TrySetTextureProperties(out_mat, textures, "DiffuseColor", aiTextureType_DIFFUSE);
- TrySetTextureProperties(out_mat, textures, "AmbientColor", aiTextureType_AMBIENT);
- TrySetTextureProperties(out_mat, textures, "EmissiveColor", aiTextureType_EMISSIVE);
- TrySetTextureProperties(out_mat, textures, "SpecularColor", aiTextureType_SPECULAR);
- TrySetTextureProperties(out_mat, textures, "TransparentColor", aiTextureType_OPACITY);
- TrySetTextureProperties(out_mat, textures, "ReflectionColor", aiTextureType_REFLECTION);
- TrySetTextureProperties(out_mat, textures, "DisplacementColor", aiTextureType_DISPLACEMENT);
- TrySetTextureProperties(out_mat, textures, "NormalMap", aiTextureType_NORMALS);
- TrySetTextureProperties(out_mat, textures, "Bump", aiTextureType_HEIGHT);
- TrySetTextureProperties(out_mat, textures, "ShininessExponent", aiTextureType_SHININESS);
+ TrySetTextureProperties(out_mat, textures, "DiffuseColor", aiTextureType_DIFFUSE, mesh);
+ TrySetTextureProperties(out_mat, textures, "AmbientColor", aiTextureType_AMBIENT, mesh);
+ TrySetTextureProperties(out_mat, textures, "EmissiveColor", aiTextureType_EMISSIVE, mesh);
+ TrySetTextureProperties(out_mat, textures, "SpecularColor", aiTextureType_SPECULAR, mesh);
+ TrySetTextureProperties(out_mat, textures, "TransparentColor", aiTextureType_OPACITY, mesh);
+ TrySetTextureProperties(out_mat, textures, "ReflectionColor", aiTextureType_REFLECTION, mesh);
+ TrySetTextureProperties(out_mat, textures, "DisplacementColor", aiTextureType_DISPLACEMENT, mesh);
+ TrySetTextureProperties(out_mat, textures, "NormalMap", aiTextureType_NORMALS, mesh);
+ TrySetTextureProperties(out_mat, textures, "Bump", aiTextureType_HEIGHT, mesh);
+ TrySetTextureProperties(out_mat, textures, "ShininessExponent", aiTextureType_SHININESS, mesh);
}
// ------------------------------------------------------------------------------------------------
- void SetTextureProperties(aiMaterial* out_mat, const LayeredTextureMap& layeredTextures)
+ void SetTextureProperties(aiMaterial* out_mat, const LayeredTextureMap& layeredTextures, const MeshGeometry* const mesh)
{
- TrySetTextureProperties(out_mat, layeredTextures, "DiffuseColor", aiTextureType_DIFFUSE);
- TrySetTextureProperties(out_mat, layeredTextures, "AmbientColor", aiTextureType_AMBIENT);
- TrySetTextureProperties(out_mat, layeredTextures, "EmissiveColor", aiTextureType_EMISSIVE);
- TrySetTextureProperties(out_mat, layeredTextures, "SpecularColor", aiTextureType_SPECULAR);
- TrySetTextureProperties(out_mat, layeredTextures, "TransparentColor", aiTextureType_OPACITY);
- TrySetTextureProperties(out_mat, layeredTextures, "ReflectionColor", aiTextureType_REFLECTION);
- TrySetTextureProperties(out_mat, layeredTextures, "DisplacementColor", aiTextureType_DISPLACEMENT);
- TrySetTextureProperties(out_mat, layeredTextures, "NormalMap", aiTextureType_NORMALS);
- TrySetTextureProperties(out_mat, layeredTextures, "Bump", aiTextureType_HEIGHT);
- TrySetTextureProperties(out_mat, layeredTextures, "ShininessExponent", aiTextureType_SHININESS);
+ TrySetTextureProperties(out_mat, layeredTextures, "DiffuseColor", aiTextureType_DIFFUSE, mesh);
+ TrySetTextureProperties(out_mat, layeredTextures, "AmbientColor", aiTextureType_AMBIENT, mesh);
+ TrySetTextureProperties(out_mat, layeredTextures, "EmissiveColor", aiTextureType_EMISSIVE, mesh);
+ TrySetTextureProperties(out_mat, layeredTextures, "SpecularColor", aiTextureType_SPECULAR, mesh);
+ TrySetTextureProperties(out_mat, layeredTextures, "TransparentColor", aiTextureType_OPACITY, mesh);
+ TrySetTextureProperties(out_mat, layeredTextures, "ReflectionColor", aiTextureType_REFLECTION, mesh);
+ TrySetTextureProperties(out_mat, layeredTextures, "DisplacementColor", aiTextureType_DISPLACEMENT, mesh);
+ TrySetTextureProperties(out_mat, layeredTextures, "NormalMap", aiTextureType_NORMALS, mesh);
+ TrySetTextureProperties(out_mat, layeredTextures, "Bump", aiTextureType_HEIGHT, mesh);
+ TrySetTextureProperties(out_mat, layeredTextures, "ShininessExponent", aiTextureType_SHININESS, mesh);
}
@@ -2298,8 +2347,8 @@ private:
// ------------------------------------------------------------------------------------------------
- aiNodeAnim* GenerateScalingNodeAnim(const std::string& name,
- const Model& /*target*/,
+ aiNodeAnim* GenerateScalingNodeAnim(const std::string& name,
+ const Model& target,
const std::vector<const AnimationCurveNode*>& curves,
const LayerMap& layer_map,
double& max_time,
@@ -2329,8 +2378,8 @@ private:
// ------------------------------------------------------------------------------------------------
- aiNodeAnim* GenerateTranslationNodeAnim(const std::string& name,
- const Model& /*target*/,
+ aiNodeAnim* GenerateTranslationNodeAnim(const std::string& name,
+ const Model& target,
const std::vector<const AnimationCurveNode*>& curves,
const LayerMap& layer_map,
double& max_time,
@@ -2782,7 +2831,7 @@ private:
// ------------------------------------------------------------------------------------------------
- void ConvertScaleKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, const LayerMap& /*layers*/,
+ void ConvertScaleKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, const LayerMap& layers,
double& maxTime,
double& minTime)
{
@@ -2803,7 +2852,7 @@ private:
// ------------------------------------------------------------------------------------------------
void ConvertTranslationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
- const LayerMap& /*layers*/,
+ const LayerMap& layers,
double& maxTime,
double& minTime)
{
@@ -2821,7 +2870,7 @@ private:
// ------------------------------------------------------------------------------------------------
void ConvertRotationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
- const LayerMap& /*layers*/,
+ const LayerMap& layers,
double& maxTime,
double& minTime,
Model::RotOrder order)
diff --git a/src/3rdparty/assimp/code/FBXImportSettings.h b/src/3rdparty/assimp/code/FBXImportSettings.h
index 47fc1d6a6..2020273d7 100644
--- a/src/3rdparty/assimp/code/FBXImportSettings.h
+++ b/src/3rdparty/assimp/code/FBXImportSettings.h
@@ -53,7 +53,7 @@ struct ImportSettings
ImportSettings()
: strictMode(true)
, readAllLayers(true)
- , readAllMaterials()
+ , readAllMaterials(false)
, readMaterials(true)
, readCameras(true)
, readLights(true)
diff --git a/src/3rdparty/assimp/code/FBXMaterial.cpp b/src/3rdparty/assimp/code/FBXMaterial.cpp
index fffa14fd3..a5e2a1169 100644
--- a/src/3rdparty/assimp/code/FBXMaterial.cpp
+++ b/src/3rdparty/assimp/code/FBXMaterial.cpp
@@ -207,7 +207,7 @@ Texture::~Texture()
}
-LayeredTexture::LayeredTexture(uint64_t id, const Element& element, const Document& /*doc*/, const std::string& name)
+LayeredTexture::LayeredTexture(uint64_t id, const Element& element, const Document& doc, const std::string& name)
: Object(id,element,name)
,texture(0)
,blendMode(BlendMode_Modulate)
diff --git a/src/3rdparty/assimp/code/FBXParser.cpp b/src/3rdparty/assimp/code/FBXParser.cpp
index 3274bca11..f6dc2e7e2 100644
--- a/src/3rdparty/assimp/code/FBXParser.cpp
+++ b/src/3rdparty/assimp/code/FBXParser.cpp
@@ -364,14 +364,24 @@ float ParseTokenAsFloat(const Token& t, const char*& err_out)
}
if (data[0] == 'F') {
- ai_assert(t.end() - data == 5);
- // no byte swapping needed for ieee floats
- return *reinterpret_cast<const float*>(data+1);
+ // Actual size validation happens during Tokenization so
+ // this is valid as an assertion.
+ ai_assert(t.end() - data == sizeof(float) + 1);
+ // Initially, we did reinterpret_cast, breaking strict aliasing rules.
+ // This actually caused trouble on Android, so let's be safe this time.
+ // https://github.com/assimp/assimp/issues/24
+
+ float out_float;
+ ::memcpy(&out_float, data+1, sizeof(float));
+ return out_float;
}
else {
- ai_assert(t.end() - data == 9);
- // no byte swapping needed for ieee floats
- return static_cast<float>(*reinterpret_cast<const double*>(data+1));
+ ai_assert(t.end() - data == sizeof(double) + 1);
+
+ // Same
+ double out_double;
+ ::memcpy(&out_double, data+1, sizeof(double));
+ return static_cast<float>(out_double);
}
}
@@ -496,7 +506,7 @@ void ReadBinaryDataArrayHead(const char*& data, const char* end, char& type, uin
// read binary data array, assume cursor points to the 'compression mode' field (i.e. behind the header)
void ReadBinaryDataArray(char type, uint32_t count, const char*& data, const char* end,
std::vector<char>& buff,
- const Element& /*el*/)
+ const Element& el)
{
ai_assert(static_cast<size_t>(end-data) >= 4); // runtime check for this happens at tokenization stage
diff --git a/src/3rdparty/assimp/code/FBXProperties.h b/src/3rdparty/assimp/code/FBXProperties.h
index 6e121cd4c..9219c3eea 100644
--- a/src/3rdparty/assimp/code/FBXProperties.h
+++ b/src/3rdparty/assimp/code/FBXProperties.h
@@ -146,7 +146,6 @@ inline T PropertyGet(const PropertyTable& in, const std::string& name,
const T& defaultValue,
bool ignoreTemplate = false)
{
- (void)ignoreTemplate; // Unused
const Property* const prop = in.Get(name);
if(!prop) {
return defaultValue;
@@ -168,7 +167,6 @@ inline T PropertyGet(const PropertyTable& in, const std::string& name,
bool& result,
bool ignoreTemplate = false)
{
- (void)ignoreTemplate; // Unused
const Property* const prop = in.Get(name);
if(!prop) {
result = false;
diff --git a/src/3rdparty/assimp/code/IFCBoolean.cpp b/src/3rdparty/assimp/code/IFCBoolean.cpp
index 7d3840710..8573e4d62 100644
--- a/src/3rdparty/assimp/code/IFCBoolean.cpp
+++ b/src/3rdparty/assimp/code/IFCBoolean.cpp
@@ -85,7 +85,7 @@ Intersect IntersectSegmentPlane(const IfcVector3& p,const IfcVector3& n, const I
// ------------------------------------------------------------------------------------------------
void ProcessBooleanHalfSpaceDifference(const IfcHalfSpaceSolid* hs, TempMesh& result,
const TempMesh& first_operand,
- ConversionData& /*conv*/)
+ ConversionData& conv)
{
ai_assert(hs != NULL);
diff --git a/src/3rdparty/assimp/code/IFCLoader.cpp b/src/3rdparty/assimp/code/IFCLoader.cpp
index 84ff9e318..9963ce70a 100644
--- a/src/3rdparty/assimp/code/IFCLoader.cpp
+++ b/src/3rdparty/assimp/code/IFCLoader.cpp
@@ -686,7 +686,7 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const IfcProduct& el, Conversion
}
// add an output node for this spatial structure
- std::unique_ptr<aiNode> nd(new aiNode());
+ std::auto_ptr<aiNode> nd(new aiNode());
nd->mName.Set(el.GetClassName()+"_"+(el.Name?el.Name.Get():"Unnamed")+"_"+el.GlobalId);
nd->mParent = parent;
@@ -773,7 +773,7 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const IfcProduct& el, Conversion
const IfcFeatureElementSubtraction& open = fills->RelatedOpeningElement;
// move opening elements to a separate node since they are semantically different than elements that are just 'contained'
- std::unique_ptr<aiNode> nd_aggr(new aiNode());
+ std::auto_ptr<aiNode> nd_aggr(new aiNode());
nd_aggr->mName.Set("$RelVoidsElement");
nd_aggr->mParent = nd.get();
@@ -818,7 +818,7 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const IfcProduct& el, Conversion
}
// move aggregate elements to a separate node since they are semantically different than elements that are just 'contained'
- std::unique_ptr<aiNode> nd_aggr(new aiNode());
+ std::auto_ptr<aiNode> nd_aggr(new aiNode());
nd_aggr->mName.Set("$RelAggregates");
nd_aggr->mParent = nd.get();
diff --git a/src/3rdparty/assimp/code/IFCMaterial.cpp b/src/3rdparty/assimp/code/IFCMaterial.cpp
index 520590965..4708cdd84 100644
--- a/src/3rdparty/assimp/code/IFCMaterial.cpp
+++ b/src/3rdparty/assimp/code/IFCMaterial.cpp
@@ -159,7 +159,7 @@ unsigned int ProcessMaterials(const IFC::IfcRepresentationItem& item, Conversion
IFCImporter::LogWarn("ignoring surface side marker on IFC::IfcSurfaceStyle: " + side);
}
- std::unique_ptr<aiMaterial> mat(new aiMaterial());
+ std::auto_ptr<aiMaterial> mat(new aiMaterial());
FillMaterial(mat.get(),surf,conv);
diff --git a/src/3rdparty/assimp/code/IFCOpenings.cpp b/src/3rdparty/assimp/code/IFCOpenings.cpp
index e212097f1..c26574cc3 100644
--- a/src/3rdparty/assimp/code/IFCOpenings.cpp
+++ b/src/3rdparty/assimp/code/IFCOpenings.cpp
@@ -259,7 +259,7 @@ BoundingBox GetBoundingBox(const ClipperLib::Polygon& poly)
// ------------------------------------------------------------------------------------------------
void InsertWindowContours(const ContourVector& contours,
- const std::vector<TempOpening>& /*openings*/,
+ const std::vector<TempOpening>& openings,
TempMesh& curmesh)
{
// fix windows - we need to insert the real, polygonal shapes into the quadratic holes that we have now
@@ -1741,4 +1741,4 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std:
#undef from_int64
#undef one_vec
-#endif
+#endif \ No newline at end of file
diff --git a/src/3rdparty/assimp/code/IFCProfile.cpp b/src/3rdparty/assimp/code/IFCProfile.cpp
index 1e2f47cbd..48ccd568e 100644
--- a/src/3rdparty/assimp/code/IFCProfile.cpp
+++ b/src/3rdparty/assimp/code/IFCProfile.cpp
@@ -101,7 +101,7 @@ void ProcessOpenProfile(const IfcArbitraryOpenProfileDef& def, TempMesh& meshout
}
// ------------------------------------------------------------------------------------------------
-void ProcessParametrizedProfile(const IfcParameterizedProfileDef& def, TempMesh& meshout, ConversionData& /*conv*/)
+void ProcessParametrizedProfile(const IfcParameterizedProfileDef& def, TempMesh& meshout, ConversionData& conv)
{
if(const IfcRectangleProfileDef* const cprofile = def.ToPtr<IfcRectangleProfileDef>()) {
const IfcFloat x = cprofile->XDim*0.5f, y = cprofile->YDim*0.5f;
diff --git a/src/3rdparty/assimp/code/IFCReaderGen.cpp b/src/3rdparty/assimp/code/IFCReaderGen.cpp
index 23361164a..c17805172 100644
--- a/src/3rdparty/assimp/code/IFCReaderGen.cpp
+++ b/src/3rdparty/assimp/code/IFCReaderGen.cpp
@@ -1045,7 +1045,7 @@ void IFC::GetSchema(EXPRESS::ConversionSchema& out)
namespace STEP {
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<NotImplemented>(const STEP::DB& /*db*/, const LIST& /*params*/, NotImplemented* /*in*/)
+template <> size_t GenericFill<NotImplemented>(const STEP::DB& db, const LIST& params, NotImplemented* in)
{
return 0;
}
@@ -1253,7 +1253,7 @@ template <> size_t GenericFill<IfcPerformanceHistory>(const DB& db, const LIST&
return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcRepresentationItem>(const DB& /*db*/, const LIST& /*params*/, IfcRepresentationItem* /*in*/)
+template <> size_t GenericFill<IfcRepresentationItem>(const DB& db, const LIST& params, IfcRepresentationItem* in)
{
size_t base = 0;
return base;
@@ -1715,7 +1715,7 @@ template <> size_t GenericFill<IfcPlateType>(const DB& db, const LIST& params, I
return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcObjectPlacement>(const DB& /*db*/, const LIST& /*params*/, IfcObjectPlacement* /*in*/)
+template <> size_t GenericFill<IfcObjectPlacement>(const DB& db, const LIST& params, IfcObjectPlacement* in)
{
size_t base = 0;
return base;
diff --git a/src/3rdparty/assimp/code/LWOAnimation.cpp b/src/3rdparty/assimp/code/LWOAnimation.cpp
index ff7270267..e1ef576ed 100644
--- a/src/3rdparty/assimp/code/LWOAnimation.cpp
+++ b/src/3rdparty/assimp/code/LWOAnimation.cpp
@@ -54,8 +54,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// internal headers
#include "LWOFileData.h"
-#include <functional>
-
using namespace Assimp;
using namespace Assimp::LWO;
diff --git a/src/3rdparty/assimp/code/M3Importer.cpp b/src/3rdparty/assimp/code/M3Importer.cpp
deleted file mode 100644
index dfbbe076e..000000000
--- a/src/3rdparty/assimp/code/M3Importer.cpp
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
-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.
-
-----------------------------------------------------------------------
-*/
-
-#include "AssimpPCH.h"
-#ifndef ASSIMP_BUILD_NO_M3_IMPORTER
-
-#include "M3Importer.h"
-#include <sstream>
-
-namespace Assimp {
-namespace M3 {
-
-static const aiImporterDesc desc = {
- "StarCraft M3 Importer",
- "",
- "",
- "",
- aiImporterFlags_SupportBinaryFlavour,
- 0,
- 0,
- 0,
- 0,
- "m3"
-};
-
-// ------------------------------------------------------------------------------------------------
-// Constructor.
-M3Importer::M3Importer() :
- m_pHead( NULL ),
- m_pRefs( NULL ),
- m_Buffer()
-{
- // empty
-}
-
-// ------------------------------------------------------------------------------------------------
-// Destructor.
-M3Importer::~M3Importer()
-{
- m_pHead = NULL;
- m_pRefs = NULL;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Check for readable file format.
-bool M3Importer::CanRead( const std::string &rFile, IOSystem* /*pIOHandler*/, bool checkSig ) const
-{
- if ( !checkSig ) {
- return SimpleExtensionCheck( rFile, "m3" );
- }
-
- return false;
-}
-
-// ------------------------------------------------------------------------------------------------
-const aiImporterDesc* M3Importer::GetInfo () const
-{
- return &desc;
-}
-
-// ------------------------------------------------------------------------------------------------
-void M3Importer::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler )
-{
- ai_assert( !pFile.empty() );
-
- const std::string mode = "rb";
- boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, mode ) );
- if ( NULL == file.get() ) {
- throw DeadlyImportError( "Failed to open file " + pFile + ".");
- }
-
- // Get the file-size and validate it, throwing an exception when it fails
- const size_t filesize = file->FileSize();
- if( filesize < 1 ) {
- throw DeadlyImportError( "M3-file is too small.");
- }
-
- m_Buffer.resize( filesize );
- size_t readsize = file->Read( &m_Buffer[ 0 ], sizeof( unsigned char ), filesize );
- ai_assert( readsize == filesize );
-
- m_pHead = reinterpret_cast<MD33*>( &m_Buffer[ 0 ] );
- m_pRefs = reinterpret_cast<ReferenceEntry*>( &m_Buffer[ 0 ] + m_pHead->ofsRefs );
-
- MODL20* pMODL20( NULL );
- MODL23* pMODL23( NULL );
-
- VertexExt* pVerts1( NULL );
- Vertex* pVerts2( NULL );
-
- DIV *pViews( NULL );
- Region* regions( NULL );
- uint16* faces( NULL );
-
- uint32 nVertices = 0;
-
- bool ok = true;
- switch( m_pRefs[ m_pHead->MODL.ref ].type ) {
- case 20:
- pMODL20 = GetEntries<MODL20>( m_pHead->MODL );
- if ( ( pMODL20->flags & 0x20000) != 0 ) { // Has vertices
- if( (pMODL20->flags & 0x40000) != 0 ) { // Has extra 4 byte
- pVerts1 = GetEntries<VertexExt>( pMODL20->vertexData );
- nVertices = pMODL20->vertexData.nEntries/sizeof(VertexExt);
- }
- else {
- pVerts2 = GetEntries<Vertex>( pMODL20->vertexData );
- nVertices = pMODL20->vertexData.nEntries / sizeof( Vertex );
- }
- }
- pViews = GetEntries<DIV>( pMODL20->views );
- break;
-
- case 23:
- pMODL23 = GetEntries<MODL23>(m_pHead->MODL );
- if( (pMODL23->flags & 0x20000) != 0 ) { // Has vertices
- if( (pMODL23->flags & 0x40000) != 0 ) { // Has extra 4 byte
- pVerts1 = GetEntries<VertexExt>( pMODL23->vertexData );
- nVertices = pMODL23->vertexData.nEntries/sizeof( VertexExt );
- }
- else {
- pVerts2 = GetEntries<Vertex>( pMODL23->vertexData );
- nVertices = pMODL23->vertexData.nEntries/sizeof( Vertex );
- }
- }
- pViews = GetEntries<DIV>( pMODL23->views );
- break;
-
- default:
- ok = false;
- break;
- }
-
- // Everything ok, if not throw an exception
- if ( !ok ) {
- throw DeadlyImportError( "Failed to open file " + pFile + ".");
- }
-
- // Get all region data
- regions = GetEntries<Region>( pViews->regions );
-
- // Get the face data
- faces = GetEntries<uint16>( pViews->faces );
-
- // Convert the vertices
- std::vector<aiVector3D> vertices;
- vertices.resize( nVertices );
- unsigned int offset = 0;
- for ( unsigned int i = 0; i < nVertices; i++ ) {
- if ( pVerts1 ) {
- vertices[ offset ].Set( pVerts1[ i ].pos.x, pVerts1[ i ].pos.y, pVerts1[ i ].pos.z );
- ++offset;
- }
-
- if ( pVerts2 ) {
- vertices[ offset ].Set( pVerts2[ i ].pos.x, pVerts2[ i ].pos.y, pVerts2[ i ].pos.z );
- ++offset;
- }
- }
-
- // Write the UV coordinates
- offset = 0;
- std::vector<aiVector3D> uvCoords;
- uvCoords.resize( nVertices );
- for( unsigned int i = 0; i < nVertices; ++i ) {
- if( pVerts1 ) {
- float u = (float) pVerts1[ i ].uv[ 0 ] / 2048;
- float v = (float) pVerts1[ i ].uv[ 1 ] / 2048;
- uvCoords[ offset ].Set( u, v, 0.0f );
- ++offset;
- }
-
- if( pVerts2 ) {
- float u = (float) pVerts2[ i ].uv[ 0 ] / 2048;
- float v = (float) pVerts2[ i ].uv[ 1 ] / 2048;
- uvCoords[ offset ].Set( u, v, 0.0f );
- ++offset;
- }
- }
-
- // Compute the normals
- std::vector<aiVector3D> normals;
- normals.resize( nVertices );
- float w = 0.0f;
- Vec3D norm;
- offset = 0;
- for( unsigned int i = 0; i < nVertices; i++ ) {
- w = 0.0f;
- if( pVerts1 ) {
- norm.x = (float) 2*pVerts1[ i ].normal[ 0 ]/255.0f - 1;
- norm.y = (float) 2*pVerts1[ i ].normal[ 1 ]/255.0f - 1;
- norm.z = (float) 2*pVerts1[ i ].normal[ 2 ]/255.0f - 1;
- w = (float) pVerts1[ i ].normal[ 3 ]/255.0f;
- }
-
- if( pVerts2 ) {
- norm.x = (float) 2*pVerts2[ i ].normal[ 0 ]/255.0f - 1;
- norm.y = (float) 2*pVerts2[ i ].normal[ 1 ]/255.0f - 1;
- norm.z = (float) 2*pVerts2[ i ].normal[ 2 ]/255.0f - 1;
- w = (float) pVerts2[ i ].normal[ 3 ] / 255.0f;
- }
-
- if ( w ) {
- const float invW = 1.0f / w;
- norm.x = norm.x * invW;
- norm.y = norm.y * invW;
- norm.z = norm.z * invW;
- normals[ offset ].Set( norm.x, norm.y, norm.z );
- ++offset;
- }
- }
-
- // Convert the data into the assimp specific data structures
- convertToAssimp( pFile, pScene, pViews, regions, faces, vertices, uvCoords, normals );
-}
-
-// ------------------------------------------------------------------------------------------------
-//
-void M3Importer::convertToAssimp( const std::string& pFile, aiScene* pScene, DIV *pViews,
- Region *pRegions, uint16 *pFaces,
- const std::vector<aiVector3D> &vertices,
- const std::vector<aiVector3D> &uvCoords,
- const std::vector<aiVector3D> &normals )
-{
- std::vector<aiMesh*> MeshArray;
-
- // Create the root node
- pScene->mRootNode = createNode( NULL );
-
- // Set the name of the scene
- pScene->mRootNode->mName.Set( pFile );
-
- aiNode *pRootNode = pScene->mRootNode;
- aiNode *pCurrentNode = NULL;
-
- // Lets create the nodes
- pRootNode->mNumChildren = pViews->regions.nEntries;
- if ( pRootNode->mNumChildren > 0 ) {
- pRootNode->mChildren = new aiNode*[ pRootNode->mNumChildren ];
- }
-
- for ( unsigned int i=0; i<pRootNode->mNumChildren; ++i ) {
- //pRegions[ i ].
- // Create a new node
- pCurrentNode = createNode( pRootNode );
- std::stringstream stream;
- stream << "Node_" << i;
- pCurrentNode->mName.Set( stream.str().c_str() );
- pRootNode->mChildren[ i ] = pCurrentNode;
-
- // Loop over the faces of the nodes
- unsigned int numFaces = ( ( pRegions[ i ].ofsIndices + pRegions[ i ].nIndices ) - pRegions[ i ].ofsIndices ) / 3;
- aiMesh *pMesh = new aiMesh;
- MeshArray.push_back( pMesh );
- pMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
-
- pMesh->mNumFaces = numFaces;
- pMesh->mFaces = new aiFace[ pMesh->mNumFaces ];
- aiFace *pCurrentFace = NULL;
- unsigned int faceIdx = 0;
- for ( unsigned int j = pRegions[ i ].ofsIndices; j < ( pRegions[ i ].ofsIndices + pRegions[ i ].nIndices ); j += 3 ) {
- pCurrentFace = &( pMesh->mFaces[ faceIdx ] );
- faceIdx++;
- pCurrentFace->mNumIndices = 3;
- pCurrentFace->mIndices = new unsigned int[ 3 ];
- pCurrentFace->mIndices[ 0 ] = pFaces[ j ];
- pCurrentFace->mIndices[ 1 ] = pFaces[ j+1 ];
- pCurrentFace->mIndices[ 2 ] = pFaces[ j+2 ];
- }
- // Now we can create the vertex data itself
- pCurrentNode->mNumMeshes = 1;
- pCurrentNode->mMeshes = new unsigned int[ 1 ];
- const unsigned int meshIdx = MeshArray.size() - 1;
- pCurrentNode->mMeshes[ 0 ] = meshIdx;
- createVertexData( pMesh, vertices, uvCoords, normals );
- }
-
- // Copy the meshes into the scene
- pScene->mNumMeshes = MeshArray.size();
- pScene->mMeshes = new aiMesh*[ MeshArray.size() ];
- unsigned int pos = 0;
- for ( std::vector<aiMesh*>::iterator it = MeshArray.begin(); it != MeshArray.end(); ++it ) {
- pScene->mMeshes[ pos ] = *it;
- ++pos;
- }
-}
-
-// ------------------------------------------------------------------------------------------------
-//
-void M3Importer::createVertexData( aiMesh *pMesh, const std::vector<aiVector3D> &vertices,
- const std::vector<aiVector3D> &uvCoords,
- const std::vector<aiVector3D> &normals )
-{
- pMesh->mNumVertices = pMesh->mNumFaces * 3;
- pMesh->mVertices = new aiVector3D[ pMesh->mNumVertices ];
- pMesh->mNumUVComponents[ 0 ] = 2;
- pMesh->mTextureCoords[ 0 ] = new aiVector3D[ pMesh->mNumVertices ];
- pMesh->mNormals = new aiVector3D[ pMesh->mNumVertices ];
- unsigned int pos = 0;
- for ( unsigned int currentFace = 0; currentFace < pMesh->mNumFaces; currentFace++ ) {
- aiFace *pFace = &( pMesh->mFaces[ currentFace ] );
- for ( unsigned int currentIdx=0; currentIdx<pFace->mNumIndices; currentIdx++ ) {
- const unsigned int idx = pFace->mIndices[ currentIdx ];
- if ( vertices.size() > idx ) {
- pMesh->mVertices[ pos ] = vertices[ idx ];
- pMesh->mNormals[ pos ] = normals[ idx ];
- pMesh->mTextureCoords[ 0 ]->x = uvCoords[ idx ].x;
- pMesh->mTextureCoords[ 0 ]->y = uvCoords[ idx ].y;
- pFace->mIndices[ currentIdx ] = pos;
- pos++;
- }
- }
- }
-}
-
-// ------------------------------------------------------------------------------------------------
-//
-aiNode *M3Importer::createNode( aiNode *pParent )
-{
- aiNode *pNode = new aiNode;
- if ( pParent )
- pNode->mParent = pParent;
- else
- pNode->mParent = NULL;
-
- return pNode;
-}
-
-// ------------------------------------------------------------------------------------------------
-
-} // Namespace M3
-} // Namespace Assimp
-
-#endif // ASSIMP_BUILD_NO_M3_IMPORTER
diff --git a/src/3rdparty/assimp/code/M3Importer.h b/src/3rdparty/assimp/code/M3Importer.h
deleted file mode 100644
index 8e079c9ca..000000000
--- a/src/3rdparty/assimp/code/M3Importer.h
+++ /dev/null
@@ -1,726 +0,0 @@
-/*
-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.
-
-----------------------------------------------------------------------
-*/
-#ifndef AI_M3LOADER_H_INCLUDED
-#define AI_M3LOADER_H_INCLUDED
-
-#include <vector>
-
-namespace Assimp {
-
-namespace M3 {
-
-// ------------------------------------------------------------------------------------------------
-// The following data definitions are from http://code.google.com/p/libm3/, many thanks for that
-// help.
-// ------------------------------------------------------------------------------------------------
-typedef unsigned char uint8;
-typedef char int8;
-typedef unsigned short uint16;
-typedef short int16;
-typedef unsigned int uint32;
-typedef int int32;
-
-class Vec3D
-{
-public:
- float x,y,z;
-
- Vec3D(float x0 = 0.0f, float y0 = 0.0f, float z0 = 0.0f) : x(x0), y(y0), z(z0) {}
-
- Vec3D(const Vec3D& v) : x(v.x), y(v.y), z(v.z) {}
-
- void reset()
- {
- x = y = z = 0.0f;
- }
-
- Vec3D& operator= (const Vec3D &v)
- {
- x = v.x;
- y = v.y;
- z = v.z;
- return *this;
- }
-
- Vec3D operator+ (const Vec3D &v) const
- {
- Vec3D r(x+v.x,y+v.y,z+v.z);
- return r;
- }
-
- Vec3D operator- (const Vec3D &v) const
- {
- Vec3D r(x-v.x,y-v.y,z-v.z);
- return r;
- }
-
- float operator* (const Vec3D &v) const
- {
- return x*v.x + y*v.y + z*v.z;
- }
-
- Vec3D operator* (float d) const
- {
- Vec3D r(x*d,y*d,z*d);
- return r;
- }
-
- Vec3D operator/ (float d) const
- {
- Vec3D r(x/d,y/d,z/d);
- return r;
- }
-
- friend Vec3D operator* (float d, const Vec3D& v)
- {
- return v * d;
- }
-
- // Cross Product
- Vec3D operator% (const Vec3D &v) const
- {
- Vec3D r(y*v.z-z*v.y, z*v.x-x*v.z, x*v.y-y*v.x);
- return r;
- }
-
- Vec3D& operator+= (const Vec3D &v)
- {
- x += v.x;
- y += v.y;
- z += v.z;
- return *this;
- }
-
- Vec3D& operator-= (const Vec3D &v)
- {
- x -= v.x;
- y -= v.y;
- z -= v.z;
- return *this;
- }
-
- Vec3D& operator*= (float d)
- {
- x *= d;
- y *= d;
- z *= d;
- return *this;
- }
-
- float lengthSquared() const
- {
- return x*x+y*y+z*z;
- }
-
- float length() const
- {
- return sqrtf(x*x+y*y+z*z);
- }
-
- Vec3D& normalize()
- {
- this->operator*= (1.0f/length());
- return *this;
- }
-
- Vec3D operator~ () const
- {
- Vec3D r(*this);
- r.normalize();
- return r;
- }
-
- operator float*()
- {
- return (float*)this;
- }
-};
-
-
-class Vec2D
-{
-public:
- float x,y;
-
- Vec2D(float x0 = 0.0f, float y0 = 0.0f) : x(x0), y(y0) {}
-
- Vec2D(const Vec2D& v) : x(v.x), y(v.y) {}
-
- Vec2D& operator= (const Vec2D &v)
- {
- x = v.x;
- y = v.y;
- return *this;
- }
-
- Vec2D operator+ (const Vec2D &v) const
- {
- Vec2D r(x+v.x,y+v.y);
- return r;
- }
-
- Vec2D operator- (const Vec2D &v) const
- {
- Vec2D r(x-v.x,y-v.y);
- return r;
- }
-
- float operator* (const Vec2D &v) const
- {
- return x*v.x + y*v.y;
- }
-
- Vec2D operator* (float d) const
- {
- Vec2D r(x*d,y*d);
- return r;
- }
-
- friend Vec2D operator* (float d, const Vec2D& v)
- {
- return v * d;
- }
-
- Vec2D& operator+= (const Vec2D &v)
- {
- x += v.x;
- y += v.y;
- return *this;
- }
-
- Vec2D& operator-= (const Vec2D &v)
- {
- x -= v.x;
- y -= v.y;
- return *this;
- }
-
- Vec2D& operator*= (float d)
- {
- x *= d;
- y *= d;
- return *this;
- }
-
- float lengthSquared() const
- {
- return x*x+y*y;
- }
-
- float length() const
- {
- return sqrtf(x*x+y*y);
- }
-
- Vec2D& normalize()
- {
- this->operator*= (1.0f/length());
- return *this;
- }
-
- Vec2D operator~ () const
- {
- Vec2D r(*this);
- r.normalize();
- return r;
- }
-
- operator float*()
- {
- return (float*)this;
- }
-};
-
-inline
-void rotate(float x0, float y0, float *x, float *y, float angle)
-{
- float xa = *x - x0, ya = *y - y0;
- *x = xa*cosf(angle) - ya*sinf(angle) + x0;
- *y = xa*sinf(angle) + ya*cosf(angle) + y0;
-}
-
-struct Reference
-{
- uint32 nEntries; // Code 0x00
- uint32 ref; // Code 0x04
-};
-
-struct ReferenceEntry
-{
- char id[ 4 ]; // Code 0x00
- uint32 offset; // Code 0x04
- uint32 nEntries; // Code 0x08
- uint32 type; // Code 0x0C
-};
-
-struct MD33
-{
- char id[4]; // Code 0x00
- uint32 ofsRefs; // Code 0x04
- uint32 nRefs; // Code 0x08
- Reference MODL; // Code 0x0C
-};
-
-enum ModelType
-{
- Type1 = 20,
- Type2 = 23
-};
-
-enum VertexFormat
-{
- Vertex_Standard,
- Vertex_Extended
-};
-
-struct MODL23
-{
- Reference name; // Code 0x00
- uint32 version; // Code 0x08
- Reference sequenceHeader; // Code 0x0C
- Reference sequenceData; // Code 0x14
- Reference sequenceLookup; // Code 0x1C
- uint32 d2; // Code 0x24
- uint32 d3; // Code 0x28
- uint32 d4; // Code 0x2C
- Reference STS; // Code 0x30
- Reference bones; // Code 0x38
- uint32 d5; // Code 0x40
- uint32 flags; // Code 0x44
- Reference vertexData; // Code 0x48
- Reference views; // Code 0x50
- Reference B; // Code 0x58
-
- Vec3D extents[2]; // Code 0x60
- float radius; // Code 0x78
-
- uint32 d7; // Code 0x7C
- uint32 d8; // Code 0x80
- uint32 d9; // Code 0x84
- uint32 d10; // Code 0x88
- uint32 d11; // Code 0x8C
- uint32 d12; // Code 0x90
- uint32 d13; // Code 0x94
- uint32 d14; // Code 0x98
- uint32 d15; // Code 0x9C
- uint32 d16; // Code 0xA0
- uint32 d17; // Code 0xA4
- uint32 d18; // Code 0xA8
- uint32 d19; // Code 0xAC
-
- Reference attachments; // Code 0xB0
- Reference attachmentLookup; // Code 0xB8
- Reference lights; // Code 0xC0
- Reference SHBX; // Code 0xC8
- Reference cameras; // Code 0xD0
- Reference D; // Code 0xD8
- Reference materialLookup; // Code 0xE0
- Reference materials; // Code 0xE8
- Reference DIS; // Code 0xF0
- Reference CMP; // Code 0xF8
-
- Reference TER; // Code 0x10
- Reference VOL; // Code 0x10
- uint32 d21; // Code 0x11
- uint32 d22; // Code 0x11
- Reference CREP; // Code 0x11
- Reference PAR; // Code 0x12
- Reference PARC; // Code 0x12
- Reference RIB; // Code 0x13
- Reference PROJ; // Code 0x13
- Reference FOR; // Code 0x14
- Reference WRP; // Code 0x14
- uint32 d24; // Code 0x15
- uint32 d25; // Code 0x15
- Reference PHRB; // Code 0x15
- uint32 d27; // Code 0x16
- uint32 d28; // Code 0x16
- uint32 d29; // Code 0x16
- uint32 d30; // Code 0x16
- uint32 d32; // Code 0x17
- uint32 d33; // Code 0x17
- Reference IKJT; // Code 0x17
- uint32 d35; // Code 0x18
- uint32 d36; // Code 0x18
- Reference PATU; // Code 0x18
- Reference TRGD; // Code 0x19
- Reference IREF; // Code 0x19
- Reference E; // Code 0x1A
- float matrix[4][4]; // Code 0x1A
- Vec3D extent[2]; // Code 0x1E
- float rad; // Code 0x20
- Reference SSGS; // Code 0x20
- Reference ATVL; // Code 0x20
- uint32 d61; // Code 0x21
- Reference F; // uint16, Code6 0x21
- Reference G; // uint16, Code 0x21
- Reference BBSC; // Code 0x22
- Reference TMD; // Code 0x22
- uint32 d62; // Code 0x23
- uint32 d63; // Code 0x23
- uint32 d64; // Code 0x23
-};
-
-struct MODL20
-{
- Reference name; // Code 0x00
- uint32 version; // Code 0x08
- Reference sequenceHeader; // Code 0x0C
- Reference sequenceData; // Code 0x14
- Reference sequenceLookup; // Code 0x1C
- uint32 d2; // Code 0x24
- uint32 d3; // Code 0x28
- uint32 d4; // Code 0x2C
- Reference STS; // Code 0x30
- Reference bones; // Code 0x38
- uint32 d5; // Code 0x44
- uint32 flags; // Code 0x44
- Reference vertexData; // uint8, Code 0x48
- Reference views; // Code 0x50
- Reference B; // uint16, Code 0x58
-
- Vec3D extents[2]; // Code 0x60
- float radius; // Code 0x78
-
- uint32 d7; // Code 0x7C
- uint32 d8; // Code 0x80
- uint32 d9; // Code 0x84
- uint32 d10; // Code 0x88
- uint32 d11; // Code 0x8C
- uint32 d12; // Code 0x90
- uint32 d13; // Code 0x94
- uint32 d14; // Code 0x98
- uint32 d15; // Code 0x9C
- uint32 d16; // Code 0xA0
- uint32 d17; // Code 0xA4
- uint32 d18; // Code 0xA8
- uint32 d19; // Code 0xAC
-
- Reference attachments; // Code 0xB0
- Reference attachmentLookup; // uint16, Code 0xB8
- Reference lights; // Code 0xC0
- Reference cameras; // Code 0xC8
- Reference D; // uint16, Code 0xD0
- Reference materialLookup; // Code 0xD8
- Reference materials; // Code 0xE0
- Reference DIS; // Code 0xE8
- Reference CMP; // Code 0xF0
- Reference TER; // Code 0xF8
-
- uint32 d20; // Code 0x10
- uint32 d21; // Code 0x10
- uint32 d22; // Code 0x10
- uint32 d23; // Code 0x10
- Reference CREP; // Code 0x11
- Reference PAR; // Code 0x11
- Reference PARC; // Code 0x12
- Reference RIB; // Code 0x12
- Reference PROJ; // Code 0x13
- Reference FOR; // Code 0x13
- uint32 d25; // Code 0x14
- uint32 d26; // Code 0x14
- uint32 d27; // Code 0x14
- uint32 d28; // Code 0x14
- Reference PHRB; // Code 0x15
- uint32 d30; // Code 0x15
- uint32 d31; // Code 0x15
- uint32 d32; // Code 0x16
- uint32 d33; // Code 0x16
- uint32 d34; // Code 0x16
- uint32 d35; // Code 0x16
- Reference IKJT; // Code 0x17
- uint32 d36; // Code 0x17
- uint32 d37; // Code 0x17
- Reference PATU; // Code 0x18
- Reference TRGD; // Code 0x18
- Reference IREF; // Code 0x19
- Reference E; // int32, Code 0x19
-
- float matrix[4][4]; // Code 0x1A
- Vec3D extent[2]; // Code 0x1E
- float rad; // Code 0x1F
-
- Reference SSGS; // Code 0x1F
- uint32 d38; // Code 0x20
- uint32 d39; // Code 0x20
- Reference BBSC; // Code 0x20
-
- uint32 d40; // Code 0x21
- uint32 d41; // Code 0x21
- uint32 d42; // Code 0x21
- uint32 d43; // Code 0x22
- uint32 d44; // Code 0x22
-};
-
-struct BONE
-{
- int32 d1; // Keybone?
- Reference name;
- uint32 flags;
- int16 parent;
- int16 s1;
-
- float floats[ 34 ];
-};
-
-struct VertexExt // 36 byte
-{
- Vec3D pos;
- uint8 boneWeight[ 4 ];
- uint8 boneIndex[ 4 ];
- uint8 normal[ 4 ]; //normal_x = (float)normal[0]/255.0f...
- int16 uv[ 2 ];
- uint32 d1;
- uint8 tangent[ 4 ];
-};
-
-struct Vertex // 32 byte
-{
- Vec3D pos;
- uint8 boneWeight[4];
- uint8 boneIndex[4];
- uint8 normal[4]; //normal_x = (float)normal[0]/255.0f...
- int16 uv[2];
- uint8 tangent[4];
-};
-
-struct MATM
-{
- uint32 d1;
- uint32 d2; // Index into MAT-table?
-};
-
-struct MAT
-{
- Reference name;
- int ukn1[ 8 ];
- float x, y; //always 1.0f
- Reference layers[13];
- int ukn2[15];
-};
-
-struct LAYR
-{
- int unk;
- Reference name;
- float unk2[85];
-};
-
-struct DIV
-{
- Reference faces; // Code 0x00
- Reference regions; // Code 0x08
- Reference BAT; // Code 0x10
- Reference MSEC; // Code 0x18
-};
-
-struct Region
-{
- uint32 unk;
- uint16 ofsVertices;
- uint16 nVertices;
- uint32 ofsIndices;
- uint32 nIndices; // reference into DIV.faces
- uint8 unknown[12];
-};
-
-struct CAM
-{
- int32 d1; // Code 0x00
- Reference name; // Code 0x04
- uint16 flags1; // Code 0x0C
- uint16 flags2; // Code 0x0E
-};
-
-struct EVNT
-{
- Reference name; // Code 0x00
- int16 unk1[4]; // Code 0x08
- float matrix[4][4]; // Code 0x10
- int32 unk2[4]; // Code 0x50
-};
-
-struct ATT
-{
- int32 unk; // Code 0x00
- Reference name; // Code 0x04
- int32 bone; // Code 0x0C
-};
-
-struct PHSH
-{
- float m[ 4 ][ 4 ];
- float f1;
- float f2;
- Reference refs[ 5 ];
- float f3;
-};
-
-struct SEQS
-{
- int32 d1; // Code 0x00
- int32 d2; // Code 0x04
- Reference name; // Code 0x08
- int32 d3; // Code 0x10
- uint32 length; // Code 0x14
- int32 d4; // Code 0x18
- uint32 flags; // Code 0x1C
- int32 unk[5]; // Code 0x20
- Vec3D extents[2]; // Code 0x34
- float radius; // Code 0x4C
- int32 d5; // Code 0x50
- int32 d6; // Code 0x54
-};
-
-struct STC
-{
- Reference name; // Code 0x00
- uint16 s1; // Code 0x08
- uint16 s2; // Code 0x0A
- uint16 s3; // Code 0x0C
- uint16 s4; // Code 0x0E
- Reference unk2; // uint32 // Code 0x12
- Reference unk3; // uint32 // Code 0x1A
- uint32 d3; // Code 0x22
- Reference evt; // Code 0x24
- Reference unk4[11]; // Seems to be transformation data // Code 0x2C
- Reference bnds; // Code 0x84
-};
-
-struct STS
-{
- Reference unk1; // uint32 // Code 0x00
- int32 unk[3]; // Code 0x08
- int16 s1; // Code 0x14
- int16 s2; // Code 0x16
-};
-
-struct STG
-{
- Reference name; // Code 0x00
- Reference stcID; // Code 0x08
-};
-
-struct SD
-{
- Reference timeline; // Code 0x00
- uint32 flags; // Code 0x08
- uint32 length; // Code 0x0C
- Reference data; // Code 0x10
-};
-
-struct BNDS
-{
- Vec3D extents1[2]; // Code 0x00
- float radius1; // Code 0x18
- Vec3D extents2[2]; // Code 0x1C
- float radius2; // Code 0x34
-};
-
-struct VEC2
-{
- float x, y;
-};
-
-struct VEC3
-{
- float x, y, z;
-};
-
-struct VEC4
-{
- float x, y, z, w;
-};
-
-struct QUAT
-{
- float x, y, z, w;
-};
-
-// ------------------------------------------------------------------------------------------------
-/** Loader to import M3-models.
- */
-// ------------------------------------------------------------------------------------------------
-class M3Importer : public BaseImporter
-{
- friend class Importer;
-
-public:
- /// @brief The default constructor.
- M3Importer();
-
- /// @brief The destructor.
- ~M3Importer();
-
- /// @brief Returns whether the class can handle the format of the given file.
- /// @remark See BaseImporter::CanRead() for details.
- bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig ) const;
-
-private:
- const aiImporterDesc* GetInfo () const;
- void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler );
- void convertToAssimp( const std::string& pFile, aiScene* pScene, DIV *pViews, Region *pRegions, uint16 *pFaces,
- const std::vector<aiVector3D> &vertices, const std::vector<aiVector3D> &uvCoords, const std::vector<aiVector3D> &normals );
- void createVertexData( aiMesh *pMesh, const std::vector<aiVector3D> &vertices, const std::vector<aiVector3D> &uvCoords,
- const std::vector<aiVector3D> &normals );
- aiNode *createNode( aiNode *pParent );
- template<typename T>
- T* GetEntries( Reference ref );
-
-private:
- MD33 *m_pHead;
- ReferenceEntry *m_pRefs;
- std::vector<unsigned char> m_Buffer;
-};
-
-// ------------------------------------------------------------------------------------------------
-template<typename T>
-inline
-T* M3Importer::GetEntries( Reference ref )
-{
- return (T*) ( &m_Buffer[ 0 ] + m_pRefs[ ref.ref ].offset );
-}
-
-// ------------------------------------------------------------------------------------------------
-
-} // Namespace M3
-} // Namespace Assimp
-
-#endif // AI_M3LOADER_H_INCLUDED
diff --git a/src/3rdparty/assimp/code/ObjFileImporter.cpp b/src/3rdparty/assimp/code/ObjFileImporter.cpp
index 97781aff4..af0038a31 100644
--- a/src/3rdparty/assimp/code/ObjFileImporter.cpp
+++ b/src/3rdparty/assimp/code/ObjFileImporter.cpp
@@ -139,7 +139,23 @@ void ObjFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
{
strModelName = pFile;
}
-
+
+ // process all '\'
+ std::vector<char> ::iterator iter = m_Buffer.begin();
+ while (iter != m_Buffer.end())
+ {
+ if (*iter == '\\')
+ {
+ // remove '\'
+ iter = m_Buffer.erase(iter);
+ // remove next character
+ while (*iter == '\r' || *iter == '\n')
+ iter = m_Buffer.erase(iter);
+ }
+ else
+ ++iter;
+ }
+
// parse the file into a temporary representation
ObjFileParser parser(m_Buffer, strModelName, pIOHandler);
diff --git a/src/3rdparty/assimp/code/OgreBinarySerializer.cpp b/src/3rdparty/assimp/code/OgreBinarySerializer.cpp
new file mode 100644
index 000000000..6674f4cee
--- /dev/null
+++ b/src/3rdparty/assimp/code/OgreBinarySerializer.cpp
@@ -0,0 +1,1110 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+
+#include "OgreBinarySerializer.h"
+#include "OgreXmlSerializer.h"
+#include "OgreParsingUtils.h"
+
+#include "TinyFormatter.h"
+
+#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
+
+// Define as 1 to get verbose logging.
+#define OGRE_BINARY_SERIALIZER_DEBUG 0
+
+namespace Assimp
+{
+namespace Ogre
+{
+
+const std::string MESH_VERSION_1_8 = "[MeshSerializer_v1.8]";
+const std::string SKELETON_VERSION_1_8 = "[Serializer_v1.80]";
+const std::string SKELETON_VERSION_1_1 = "[Serializer_v1.10]";
+
+const unsigned short HEADER_CHUNK_ID = 0x1000;
+
+const long MSTREAM_OVERHEAD_SIZE = sizeof(uint16_t) + sizeof(uint32_t);
+const long MSTREAM_BONE_SIZE_WITHOUT_SCALE = MSTREAM_OVERHEAD_SIZE + sizeof(unsigned short) + (sizeof(float) * 7);
+const long MSTREAM_KEYFRAME_SIZE_WITHOUT_SCALE = MSTREAM_OVERHEAD_SIZE + (sizeof(float) * 8);
+
+template<>
+inline bool OgreBinarySerializer::Read<bool>()
+{
+ return (m_reader->GetU1() > 0);
+}
+
+template<>
+inline char OgreBinarySerializer::Read<char>()
+{
+ return static_cast<char>(m_reader->GetU1());
+}
+
+template<>
+inline uint8_t OgreBinarySerializer::Read<uint8_t>()
+{
+ return m_reader->GetU1();
+}
+
+template<>
+inline uint16_t OgreBinarySerializer::Read<uint16_t>()
+{
+ return m_reader->GetU2();
+}
+
+template<>
+inline uint32_t OgreBinarySerializer::Read<uint32_t>()
+{
+ return m_reader->GetU4();
+}
+
+template<>
+inline float OgreBinarySerializer::Read<float>()
+{
+ return m_reader->GetF4();
+}
+
+void OgreBinarySerializer::ReadBytes(char *dest, size_t numBytes)
+{
+ ReadBytes(static_cast<void*>(dest), numBytes);
+}
+
+void OgreBinarySerializer::ReadBytes(uint8_t *dest, size_t numBytes)
+{
+ ReadBytes(static_cast<void*>(dest), numBytes);
+}
+
+void OgreBinarySerializer::ReadBytes(void *dest, size_t numBytes)
+{
+ m_reader->CopyAndAdvance(dest, numBytes);
+}
+
+uint8_t *OgreBinarySerializer::ReadBytes(size_t numBytes)
+{
+ uint8_t *bytes = new uint8_t[numBytes];
+ ReadBytes(bytes, numBytes);
+ return bytes;
+}
+
+void OgreBinarySerializer::ReadVector(aiVector3D &vec)
+{
+ m_reader->CopyAndAdvance(&vec.x, sizeof(float)*3);
+}
+
+void OgreBinarySerializer::ReadQuaternion(aiQuaternion &quat)
+{
+ float temp[4];
+ m_reader->CopyAndAdvance(temp, sizeof(float)*4);
+ quat.x = temp[0];
+ quat.y = temp[1];
+ quat.z = temp[2];
+ quat.w = temp[3];
+}
+
+bool OgreBinarySerializer::AtEnd() const
+{
+ return (m_reader->GetRemainingSize() == 0);
+}
+
+std::string OgreBinarySerializer::ReadString(size_t len)
+{
+ std::string str;
+ str.resize(len);
+ ReadBytes(&str[0], len);
+ return str;
+}
+
+std::string OgreBinarySerializer::ReadLine()
+{
+ std::string str;
+ while(!AtEnd())
+ {
+ char c = Read<char>();
+ if (c == '\n')
+ break;
+ str += c;
+ }
+ return str;
+}
+
+uint16_t OgreBinarySerializer::ReadHeader(bool readLen)
+{
+ uint16_t id = Read<uint16_t>();
+ if (readLen)
+ m_currentLen = Read<uint32_t>();
+
+#if (OGRE_BINARY_SERIALIZER_DEBUG == 1)
+ if (id != HEADER_CHUNK_ID)
+ {
+ DefaultLogger::get()->debug(Formatter::format() << (assetMode == AM_Mesh
+ ? MeshHeaderToString(static_cast<MeshChunkId>(id)) : SkeletonHeaderToString(static_cast<SkeletonChunkId>(id))));
+ }
+#endif
+
+ return id;
+}
+
+void OgreBinarySerializer::RollbackHeader()
+{
+ m_reader->IncPtr(-MSTREAM_OVERHEAD_SIZE);
+}
+
+void OgreBinarySerializer::SkipBytes(size_t numBytes)
+{
+#if (OGRE_BINARY_SERIALIZER_DEBUG == 1)
+ DefaultLogger::get()->debug(Formatter::format() << "Skipping " << numBytes << " bytes");
+#endif
+
+ m_reader->IncPtr(numBytes);
+}
+
+// Mesh
+
+Mesh *OgreBinarySerializer::ImportMesh(MemoryStreamReader *stream)
+{
+ OgreBinarySerializer serializer(stream, OgreBinarySerializer::AM_Mesh);
+
+ uint16_t id = serializer.ReadHeader(false);
+ if (id != HEADER_CHUNK_ID) {
+ throw DeadlyExportError("Invalid Ogre Mesh file header.");
+ }
+
+ /// @todo Check what we can actually support.
+ std::string version = serializer.ReadLine();
+ if (version != MESH_VERSION_1_8)
+ {
+ throw DeadlyExportError(Formatter::format() << "Mesh version " << version << " not supported by this importer. Run OgreMeshUpgrader tool on the file and try again."
+ << " Supported versions: " << MESH_VERSION_1_8);
+ }
+
+ Mesh *mesh = new Mesh();
+ while (!serializer.AtEnd())
+ {
+ id = serializer.ReadHeader();
+ switch(id)
+ {
+ case M_MESH:
+ {
+ serializer.ReadMesh(mesh);
+ break;
+ }
+ }
+ }
+ return mesh;
+}
+
+void OgreBinarySerializer::ReadMesh(Mesh *mesh)
+{
+ mesh->hasSkeletalAnimations = Read<bool>();
+
+ DefaultLogger::get()->debug("Reading Mesh");
+ DefaultLogger::get()->debug(Formatter::format() << " - Skeletal animations: " << (mesh->hasSkeletalAnimations ? "true" : "false"));
+
+ if (!AtEnd())
+ {
+ uint16_t id = ReadHeader();
+ while (!AtEnd() &&
+ (id == M_GEOMETRY ||
+ id == M_SUBMESH ||
+ id == M_MESH_SKELETON_LINK ||
+ id == M_MESH_BONE_ASSIGNMENT ||
+ id == M_MESH_LOD ||
+ id == M_MESH_BOUNDS ||
+ id == M_SUBMESH_NAME_TABLE ||
+ id == M_EDGE_LISTS ||
+ id == M_POSES ||
+ id == M_ANIMATIONS ||
+ id == M_TABLE_EXTREMES))
+ {
+ switch(id)
+ {
+ case M_GEOMETRY:
+ {
+ mesh->sharedVertexData = new VertexData();
+ ReadGeometry(mesh->sharedVertexData);
+ break;
+ }
+ case M_SUBMESH:
+ {
+ ReadSubMesh(mesh);
+ break;
+ }
+ case M_MESH_SKELETON_LINK:
+ {
+ ReadMeshSkeletonLink(mesh);
+ break;
+ }
+ case M_MESH_BONE_ASSIGNMENT:
+ {
+ ReadBoneAssignment(mesh->sharedVertexData);
+ break;
+ }
+ case M_MESH_LOD:
+ {
+ ReadMeshLodInfo(mesh);
+ break;
+ }
+ case M_MESH_BOUNDS:
+ {
+ ReadMeshBounds(mesh);
+ break;
+ }
+ case M_SUBMESH_NAME_TABLE:
+ {
+ ReadSubMeshNames(mesh);
+ break;
+ }
+ case M_EDGE_LISTS:
+ {
+ ReadEdgeList(mesh);
+ break;
+ }
+ case M_POSES:
+ {
+ ReadPoses(mesh);
+ break;
+ }
+ case M_ANIMATIONS:
+ {
+ ReadAnimations(mesh);
+ break;
+ }
+ case M_TABLE_EXTREMES:
+ {
+ ReadMeshExtremes(mesh);
+ break;
+ }
+ }
+
+ if (!AtEnd())
+ id = ReadHeader();
+ }
+ if (!AtEnd())
+ RollbackHeader();
+ }
+
+ NormalizeBoneWeights(mesh->sharedVertexData);
+}
+
+void OgreBinarySerializer::ReadMeshLodInfo(Mesh *mesh)
+{
+ // Assimp does not acknowledge LOD levels as far as I can see it. This info is just skipped.
+ // @todo Put this stuff to scene/mesh custom properties. If manual mesh the app can use the information.
+ ReadLine(); // strategy name
+ uint16_t numLods = Read<uint16_t>();
+ bool manual = Read<bool>();
+
+ /// @note Main mesh is considered as LOD 0, start from index 1.
+ for (size_t i=1; i<numLods; ++i)
+ {
+ uint16_t id = ReadHeader();
+ if (id != M_MESH_LOD_USAGE) {
+ throw DeadlyImportError("M_MESH_LOD does not contain a M_MESH_LOD_USAGE for each LOD level");
+ }
+
+ m_reader->IncPtr(sizeof(float)); // user value
+
+ if (manual)
+ {
+ id = ReadHeader();
+ if (id != M_MESH_LOD_MANUAL) {
+ throw DeadlyImportError("Manual M_MESH_LOD_USAGE does not contain M_MESH_LOD_MANUAL");
+ }
+
+ ReadLine(); // manual mesh name (ref to another mesh)
+ }
+ else
+ {
+ for(size_t si=0, silen=mesh->NumSubMeshes(); si<silen; ++si)
+ {
+ id = ReadHeader();
+ if (id != M_MESH_LOD_GENERATED) {
+ throw DeadlyImportError("Generated M_MESH_LOD_USAGE does not contain M_MESH_LOD_GENERATED");
+ }
+
+ uint32_t indexCount = Read<uint32_t>();
+ bool is32bit = Read<bool>();
+
+ if (indexCount > 0)
+ {
+ uint32_t len = indexCount * (is32bit ? sizeof(uint32_t) : sizeof(uint16_t));
+ m_reader->IncPtr(len);
+ }
+ }
+ }
+ }
+}
+
+void OgreBinarySerializer::ReadMeshSkeletonLink(Mesh *mesh)
+{
+ mesh->skeletonRef = ReadLine();
+}
+
+void OgreBinarySerializer::ReadMeshBounds(Mesh *mesh)
+{
+ // Skip bounds, not compatible with Assimp.
+ // 2x float vec3 + 1x float sphere radius
+ SkipBytes(sizeof(float) * 7);
+}
+
+void OgreBinarySerializer::ReadMeshExtremes(Mesh *mesh)
+{
+ // Skip extremes, not compatible with Assimp.
+ size_t numBytes = m_currentLen - MSTREAM_OVERHEAD_SIZE;
+ SkipBytes(numBytes);
+}
+
+void OgreBinarySerializer::ReadBoneAssignment(VertexData *dest)
+{
+ if (!dest) {
+ throw DeadlyImportError("Cannot read bone assignments, vertex data is null.");
+ }
+
+ VertexBoneAssignment ba;
+ ba.vertexIndex = Read<uint32_t>();
+ ba.boneIndex = Read<uint16_t>();
+ ba.weight = Read<float>();
+
+ dest->boneAssignments.push_back(ba);
+}
+
+void OgreBinarySerializer::ReadSubMesh(Mesh *mesh)
+{
+ uint16_t id = 0;
+
+ SubMesh *submesh = new SubMesh();
+ submesh->materialRef = ReadLine();
+ submesh->usesSharedVertexData = Read<bool>();
+
+ submesh->indexData->count = Read<uint32_t>();
+ submesh->indexData->faceCount = static_cast<uint32_t>(submesh->indexData->count / 3);
+ submesh->indexData->is32bit = Read<bool>();
+
+ DefaultLogger::get()->debug(Formatter::format() << "Reading SubMesh " << mesh->subMeshes.size());
+ DefaultLogger::get()->debug(Formatter::format() << " - Material: '" << submesh->materialRef << "'");
+ DefaultLogger::get()->debug(Formatter::format() << " - Uses shared geometry: " << (submesh->usesSharedVertexData ? "true" : "false"));
+
+ // Index buffer
+ if (submesh->indexData->count > 0)
+ {
+ uint32_t numBytes = submesh->indexData->count * (submesh->indexData->is32bit ? sizeof(uint32_t) : sizeof(uint16_t));
+ uint8_t *indexBuffer = ReadBytes(numBytes);
+ submesh->indexData->buffer = MemoryStreamPtr(new Assimp::MemoryIOStream(indexBuffer, numBytes, true));
+
+ DefaultLogger::get()->debug(Formatter::format() << " - " << submesh->indexData->faceCount
+ << " faces from " << submesh->indexData->count << (submesh->indexData->is32bit ? " 32bit" : " 16bit")
+ << " indexes of " << numBytes << " bytes");
+ }
+
+ // Vertex buffer if not referencing the shared geometry
+ if (!submesh->usesSharedVertexData)
+ {
+ id = ReadHeader();
+ if (id != M_GEOMETRY) {
+ throw DeadlyImportError("M_SUBMESH does not contain M_GEOMETRY, but shader geometry is set to false");
+ }
+
+ submesh->vertexData = new VertexData();
+ ReadGeometry(submesh->vertexData);
+ }
+
+ // Bone assignment, submesh operation and texture aliases
+ if (!AtEnd())
+ {
+ id = ReadHeader();
+ while (!AtEnd() &&
+ (id == M_SUBMESH_OPERATION ||
+ id == M_SUBMESH_BONE_ASSIGNMENT ||
+ id == M_SUBMESH_TEXTURE_ALIAS))
+ {
+ switch(id)
+ {
+ case M_SUBMESH_OPERATION:
+ {
+ ReadSubMeshOperation(submesh);
+ break;
+ }
+ case M_SUBMESH_BONE_ASSIGNMENT:
+ {
+ ReadBoneAssignment(submesh->vertexData);
+ break;
+ }
+ case M_SUBMESH_TEXTURE_ALIAS:
+ {
+ ReadSubMeshTextureAlias(submesh);
+ break;
+ }
+ }
+
+ if (!AtEnd())
+ id = ReadHeader();
+ }
+ if (!AtEnd())
+ RollbackHeader();
+ }
+
+ NormalizeBoneWeights(submesh->vertexData);
+
+ submesh->index = mesh->subMeshes.size();
+ mesh->subMeshes.push_back(submesh);
+}
+
+void OgreBinarySerializer::NormalizeBoneWeights(VertexData *vertexData) const
+{
+ if (!vertexData || vertexData->boneAssignments.empty())
+ return;
+
+ std::set<uint32_t> influencedVertices;
+ for (VertexBoneAssignmentList::const_iterator baIter=vertexData->boneAssignments.begin(), baEnd=vertexData->boneAssignments.end(); baIter != baEnd; ++baIter) {
+ influencedVertices.insert(baIter->vertexIndex);
+ }
+
+ /** Normalize bone weights.
+ Some exporters wont care if the sum of all bone weights
+ for a single vertex equals 1 or not, so validate here. */
+ const float epsilon = 0.05f;
+ for(std::set<uint32_t>::const_iterator iter=influencedVertices.begin(), end=influencedVertices.end(); iter != end; ++iter)
+ {
+ const uint32_t vertexIndex = (*iter);
+
+ float sum = 0.0f;
+ for (VertexBoneAssignmentList::const_iterator baIter=vertexData->boneAssignments.begin(), baEnd=vertexData->boneAssignments.end(); baIter != baEnd; ++baIter)
+ {
+ if (baIter->vertexIndex == vertexIndex)
+ sum += baIter->weight;
+ }
+ if ((sum < (1.0f - epsilon)) || (sum > (1.0f + epsilon)))
+ {
+ for (VertexBoneAssignmentList::iterator baIter=vertexData->boneAssignments.begin(), baEnd=vertexData->boneAssignments.end(); baIter != baEnd; ++baIter)
+ {
+ if (baIter->vertexIndex == vertexIndex)
+ baIter->weight /= sum;
+ }
+ }
+ }
+}
+
+void OgreBinarySerializer::ReadSubMeshOperation(SubMesh *submesh)
+{
+ submesh->operationType = static_cast<SubMesh::OperationType>(Read<uint16_t>());
+}
+
+void OgreBinarySerializer::ReadSubMeshTextureAlias(SubMesh *submesh)
+{
+ submesh->textureAliasName = ReadLine();
+ submesh->textureAliasRef = ReadLine();
+}
+
+void OgreBinarySerializer::ReadSubMeshNames(Mesh *mesh)
+{
+ uint16_t id = 0;
+ uint16_t submeshIndex = 0;
+
+ if (!AtEnd())
+ {
+ id = ReadHeader();
+ while (!AtEnd() && id == M_SUBMESH_NAME_TABLE_ELEMENT)
+ {
+ uint16_t submeshIndex = Read<uint16_t>();
+ SubMesh *submesh = mesh->GetSubMesh(submeshIndex);
+ if (!submesh) {
+ throw DeadlyImportError(Formatter::format() << "Ogre Mesh does not include submesh " << submeshIndex << " referenced in M_SUBMESH_NAME_TABLE_ELEMENT. Invalid mesh file.");
+ }
+
+ submesh->name = ReadLine();
+ DefaultLogger::get()->debug(Formatter::format() << " - SubMesh " << submesh->index << " name '" << submesh->name << "'");
+
+ if (!AtEnd())
+ id = ReadHeader();
+ }
+ if (!AtEnd())
+ RollbackHeader();
+ }
+}
+
+void OgreBinarySerializer::ReadGeometry(VertexData *dest)
+{
+ dest->count = Read<uint32_t>();
+
+ DefaultLogger::get()->debug(Formatter::format() << " - Reading geometry of " << dest->count << " vertices");
+
+ if (!AtEnd())
+ {
+ uint16_t id = ReadHeader();
+ while (!AtEnd() &&
+ (id == M_GEOMETRY_VERTEX_DECLARATION ||
+ id == M_GEOMETRY_VERTEX_BUFFER))
+ {
+ switch(id)
+ {
+ case M_GEOMETRY_VERTEX_DECLARATION:
+ {
+ ReadGeometryVertexDeclaration(dest);
+ break;
+ }
+ case M_GEOMETRY_VERTEX_BUFFER:
+ {
+ ReadGeometryVertexBuffer(dest);
+ break;
+ }
+ }
+
+ if (!AtEnd())
+ id = ReadHeader();
+ }
+ if (!AtEnd())
+ RollbackHeader();
+ }
+}
+
+void OgreBinarySerializer::ReadGeometryVertexDeclaration(VertexData *dest)
+{
+ if (!AtEnd())
+ {
+ uint16_t id = ReadHeader();
+ while (!AtEnd() && id == M_GEOMETRY_VERTEX_ELEMENT)
+ {
+ ReadGeometryVertexElement(dest);
+
+ if (!AtEnd())
+ id = ReadHeader();
+ }
+ if (!AtEnd())
+ RollbackHeader();
+ }
+}
+
+void OgreBinarySerializer::ReadGeometryVertexElement(VertexData *dest)
+{
+ VertexElement element;
+ element.source = Read<uint16_t>();
+ element.type = static_cast<VertexElement::Type>(Read<uint16_t>());
+ element.semantic = static_cast<VertexElement::Semantic>(Read<uint16_t>());
+ element.offset = Read<uint16_t>();
+ element.index = Read<uint16_t>();
+
+ DefaultLogger::get()->debug(Formatter::format() << " - Vertex element " << element.SemanticToString() << " of type "
+ << element.TypeToString() << " index=" << element.index << " source=" << element.source);
+
+ dest->vertexElements.push_back(element);
+}
+
+void OgreBinarySerializer::ReadGeometryVertexBuffer(VertexData *dest)
+{
+ uint16_t bindIndex = Read<uint16_t>();
+ uint16_t vertexSize = Read<uint16_t>();
+
+ uint16_t id = ReadHeader();
+ if (id != M_GEOMETRY_VERTEX_BUFFER_DATA)
+ throw DeadlyImportError("M_GEOMETRY_VERTEX_BUFFER_DATA not found in M_GEOMETRY_VERTEX_BUFFER");
+
+ if (dest->VertexSize(bindIndex) != vertexSize)
+ throw DeadlyImportError("Vertex buffer size does not agree with vertex declaration in M_GEOMETRY_VERTEX_BUFFER");
+
+ size_t numBytes = dest->count * vertexSize;
+ uint8_t *vertexBuffer = ReadBytes(numBytes);
+ dest->vertexBindings[bindIndex] = MemoryStreamPtr(new Assimp::MemoryIOStream(vertexBuffer, numBytes, true));
+
+ DefaultLogger::get()->debug(Formatter::format() << " - Read vertex buffer for source " << bindIndex << " of " << numBytes << " bytes");
+}
+
+void OgreBinarySerializer::ReadEdgeList(Mesh *mesh)
+{
+ // Assimp does not acknowledge LOD levels as far as I can see it. This info is just skipped.
+
+ if (!AtEnd())
+ {
+ uint16_t id = ReadHeader();
+ while (!AtEnd() && id == M_EDGE_LIST_LOD)
+ {
+ m_reader->IncPtr(sizeof(uint16_t)); // lod index
+ bool manual = Read<bool>();
+
+ if (!manual)
+ {
+ m_reader->IncPtr(sizeof(uint8_t));
+ uint32_t numTriangles = Read<uint32_t>();
+ uint32_t numEdgeGroups = Read<uint32_t>();
+
+ size_t skipBytes = (sizeof(uint32_t) * 8 + sizeof(float) * 4) * numTriangles;
+ m_reader->IncPtr(skipBytes);
+
+ for (size_t i=0; i<numEdgeGroups; ++i)
+ {
+ uint16_t id = ReadHeader();
+ if (id != M_EDGE_GROUP)
+ throw DeadlyImportError("M_EDGE_GROUP not found in M_EDGE_LIST_LOD");
+
+ m_reader->IncPtr(sizeof(uint32_t) * 3);
+ uint32_t numEdges = Read<uint32_t>();
+ for (size_t j=0; j<numEdges; ++j)
+ {
+ m_reader->IncPtr(sizeof(uint32_t) * 6 + sizeof(uint8_t));
+ }
+ }
+ }
+
+ if (!AtEnd())
+ id = ReadHeader();
+ }
+ if (!AtEnd())
+ RollbackHeader();
+ }
+}
+
+void OgreBinarySerializer::ReadPoses(Mesh *mesh)
+{
+ if (!AtEnd())
+ {
+ uint16_t id = ReadHeader();
+ while (!AtEnd() && id == M_POSE)
+ {
+ Pose *pose = new Pose();
+ pose->name = ReadLine();
+ pose->target = Read<uint16_t>();
+ pose->hasNormals = Read<bool>();
+
+ ReadPoseVertices(pose);
+
+ mesh->poses.push_back(pose);
+
+ if (!AtEnd())
+ id = ReadHeader();
+ }
+ if (!AtEnd())
+ RollbackHeader();
+ }
+}
+
+void OgreBinarySerializer::ReadPoseVertices(Pose *pose)
+{
+ if (!AtEnd())
+ {
+ uint16_t id = ReadHeader();
+ while (!AtEnd() && id == M_POSE_VERTEX)
+ {
+ Pose::Vertex v;
+ v.index = Read<uint32_t>();
+ ReadVector(v.offset);
+ if (pose->hasNormals)
+ ReadVector(v.normal);
+
+ pose->vertices[v.index] = v;
+
+ if (!AtEnd())
+ id = ReadHeader();
+ }
+ if (!AtEnd())
+ RollbackHeader();
+ }
+}
+
+void OgreBinarySerializer::ReadAnimations(Mesh *mesh)
+{
+ if (!AtEnd())
+ {
+ uint16_t id = ReadHeader();
+ while (!AtEnd() && id == M_ANIMATION)
+ {
+ Animation *anim = new Animation(mesh);
+ anim->name = ReadLine();
+ anim->length = Read<float>();
+
+ ReadAnimation(anim);
+
+ mesh->animations.push_back(anim);
+
+ if (!AtEnd())
+ id = ReadHeader();
+ }
+ if (!AtEnd())
+ RollbackHeader();
+ }
+}
+
+void OgreBinarySerializer::ReadAnimation(Animation *anim)
+{
+ if (!AtEnd())
+ {
+ uint16_t id = ReadHeader();
+ if (id == M_ANIMATION_BASEINFO)
+ {
+ anim->baseName = ReadLine();
+ anim->baseTime = Read<float>();
+
+ // Advance to first track
+ id = ReadHeader();
+ }
+
+ while (!AtEnd() && id == M_ANIMATION_TRACK)
+ {
+ VertexAnimationTrack track;
+ track.type = static_cast<VertexAnimationTrack::Type>(Read<uint16_t>());
+ track.target = Read<uint16_t>();
+
+ ReadAnimationKeyFrames(anim, &track);
+
+ anim->tracks.push_back(track);
+
+ if (!AtEnd())
+ id = ReadHeader();
+ }
+ if (!AtEnd())
+ RollbackHeader();
+ }
+}
+
+void OgreBinarySerializer::ReadAnimationKeyFrames(Animation *anim, VertexAnimationTrack *track)
+{
+ if (!AtEnd())
+ {
+ uint16_t id = ReadHeader();
+ while (!AtEnd() &&
+ (id == M_ANIMATION_MORPH_KEYFRAME ||
+ id == M_ANIMATION_POSE_KEYFRAME))
+ {
+ if (id == M_ANIMATION_MORPH_KEYFRAME)
+ {
+ MorphKeyFrame kf;
+ kf.timePos = Read<float>();
+ bool hasNormals = Read<bool>();
+
+ size_t vertexCount = anim->AssociatedVertexData(track)->count;
+ size_t vertexSize = sizeof(float) * (hasNormals ? 6 : 3);
+ size_t numBytes = vertexCount * vertexSize;
+
+ uint8_t *morphBuffer = ReadBytes(numBytes);
+ kf.buffer = MemoryStreamPtr(new Assimp::MemoryIOStream(morphBuffer, numBytes, true));
+
+ track->morphKeyFrames.push_back(kf);
+ }
+ else if (id == M_ANIMATION_POSE_KEYFRAME)
+ {
+ PoseKeyFrame kf;
+ kf.timePos = Read<float>();
+
+ if (!AtEnd())
+ {
+ id = ReadHeader();
+ while (!AtEnd() && id == M_ANIMATION_POSE_REF)
+ {
+ PoseRef pr;
+ pr.index = Read<uint16_t>();
+ pr.influence = Read<float>();
+ kf.references.push_back(pr);
+
+ if (!AtEnd())
+ id = ReadHeader();
+ }
+ if (!AtEnd())
+ RollbackHeader();
+ }
+
+ track->poseKeyFrames.push_back(kf);
+ }
+
+ if (!AtEnd())
+ id = ReadHeader();
+ }
+ if (!AtEnd())
+ RollbackHeader();
+ }
+}
+
+// Skeleton
+
+bool OgreBinarySerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, Mesh *mesh)
+{
+ if (!mesh || mesh->skeletonRef.empty())
+ return false;
+
+ // Highly unusual to see in read world cases but support
+ // binary mesh referencing a XML skeleton file.
+ if (EndsWith(mesh->skeletonRef, ".skeleton.xml", false))
+ {
+ OgreXmlSerializer::ImportSkeleton(pIOHandler, mesh);
+ return false;
+ }
+
+ MemoryStreamReaderPtr reader = OpenReader(pIOHandler, mesh->skeletonRef);
+
+ Skeleton *skeleton = new Skeleton();
+ OgreBinarySerializer serializer(reader.get(), OgreBinarySerializer::AM_Skeleton);
+ serializer.ReadSkeleton(skeleton);
+ mesh->skeleton = skeleton;
+ return true;
+}
+
+bool OgreBinarySerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, MeshXml *mesh)
+{
+ if (!mesh || mesh->skeletonRef.empty())
+ return false;
+
+ MemoryStreamReaderPtr reader = OpenReader(pIOHandler, mesh->skeletonRef);
+ if (!reader.get())
+ return false;
+
+ Skeleton *skeleton = new Skeleton();
+ OgreBinarySerializer serializer(reader.get(), OgreBinarySerializer::AM_Skeleton);
+ serializer.ReadSkeleton(skeleton);
+ mesh->skeleton = skeleton;
+ return true;
+}
+
+MemoryStreamReaderPtr OgreBinarySerializer::OpenReader(Assimp::IOSystem *pIOHandler, const std::string &filename)
+{
+ if (!EndsWith(filename, ".skeleton", false))
+ {
+ DefaultLogger::get()->error("Imported Mesh is referencing to unsupported '" + filename + "' skeleton file.");
+ return MemoryStreamReaderPtr();
+ }
+
+ if (!pIOHandler->Exists(filename))
+ {
+ DefaultLogger::get()->error("Failed to find skeleton file '" + filename + "' that is referenced by imported Mesh.");
+ return MemoryStreamReaderPtr();
+ }
+
+ IOStream *f = pIOHandler->Open(filename, "rb");
+ if (!f) {
+ throw DeadlyImportError("Failed to open skeleton file " + filename);
+ }
+
+ return MemoryStreamReaderPtr(new MemoryStreamReader(f));
+}
+
+void OgreBinarySerializer::ReadSkeleton(Skeleton *skeleton)
+{
+ uint16_t id = ReadHeader(false);
+ if (id != HEADER_CHUNK_ID) {
+ throw DeadlyExportError("Invalid Ogre Skeleton file header.");
+ }
+
+ // This deserialization supports both versions of the skeleton spec
+ std::string version = ReadLine();
+ if (version != SKELETON_VERSION_1_8 && version != SKELETON_VERSION_1_1)
+ {
+ throw DeadlyExportError(Formatter::format() << "Skeleton version " << version << " not supported by this importer."
+ << " Supported versions: " << SKELETON_VERSION_1_8 << " and " << SKELETON_VERSION_1_1);
+ }
+
+ DefaultLogger::get()->debug("Reading Skeleton");
+
+ bool firstBone = true;
+ bool firstAnim = true;
+
+ while (!AtEnd())
+ {
+ id = ReadHeader();
+ switch(id)
+ {
+ case SKELETON_BLENDMODE:
+ {
+ skeleton->blendMode = static_cast<Skeleton::BlendMode>(Read<uint16_t>());
+ break;
+ }
+ case SKELETON_BONE:
+ {
+ if (firstBone)
+ {
+ DefaultLogger::get()->debug(" - Bones");
+ firstBone = false;
+ }
+
+ ReadBone(skeleton);
+ break;
+ }
+ case SKELETON_BONE_PARENT:
+ {
+ ReadBoneParent(skeleton);
+ break;
+ }
+ case SKELETON_ANIMATION:
+ {
+ if (firstAnim)
+ {
+ DefaultLogger::get()->debug(" - Animations");
+ firstAnim = false;
+ }
+
+ ReadSkeletonAnimation(skeleton);
+ break;
+ }
+ case SKELETON_ANIMATION_LINK:
+ {
+ ReadSkeletonAnimationLink(skeleton);
+ break;
+ }
+ }
+ }
+
+ // Calculate bone matrices for root bones. Recursively calculates their children.
+ for (size_t i=0, len=skeleton->bones.size(); i<len; ++i)
+ {
+ Bone *bone = skeleton->bones[i];
+ if (!bone->IsParented())
+ bone->CalculateWorldMatrixAndDefaultPose(skeleton);
+ }
+}
+
+void OgreBinarySerializer::ReadBone(Skeleton *skeleton)
+{
+ Bone *bone = new Bone();
+ bone->name = ReadLine();
+ bone->id = Read<uint16_t>();
+
+ // Pos and rot
+ ReadVector(bone->position);
+ ReadQuaternion(bone->rotation);
+
+ // Scale (optional)
+ if (m_currentLen > MSTREAM_BONE_SIZE_WITHOUT_SCALE)
+ ReadVector(bone->scale);
+
+ // Bone indexes need to start from 0 and be contiguous
+ if (bone->id != skeleton->bones.size()) {
+ throw DeadlyImportError(Formatter::format() << "Ogre Skeleton bone indexes not contiguous. Error at bone index " << bone->id);
+ }
+
+ DefaultLogger::get()->debug(Formatter::format() << " " << bone->id << " " << bone->name);
+
+ skeleton->bones.push_back(bone);
+}
+
+void OgreBinarySerializer::ReadBoneParent(Skeleton *skeleton)
+{
+ uint16_t childId = Read<uint16_t>();
+ uint16_t parentId = Read<uint16_t>();
+
+ Bone *child = skeleton->BoneById(childId);
+ Bone *parent = skeleton->BoneById(parentId);
+
+ if (child && parent)
+ parent->AddChild(child);
+ else
+ throw DeadlyImportError(Formatter::format() << "Failed to find bones for parenting: Child id " << childId << " for parent id " << parentId);
+}
+
+void OgreBinarySerializer::ReadSkeletonAnimation(Skeleton *skeleton)
+{
+ Animation *anim = new Animation(skeleton);
+ anim->name = ReadLine();
+ anim->length = Read<float>();
+
+ if (!AtEnd())
+ {
+ uint16_t id = ReadHeader();
+ if (id == SKELETON_ANIMATION_BASEINFO)
+ {
+ anim->baseName = ReadLine();
+ anim->baseTime = Read<float>();
+
+ // Advance to first track
+ id = ReadHeader();
+ }
+
+ while (!AtEnd() && id == SKELETON_ANIMATION_TRACK)
+ {
+ ReadSkeletonAnimationTrack(skeleton, anim);
+
+ if (!AtEnd())
+ id = ReadHeader();
+ }
+ if (!AtEnd())
+ RollbackHeader();
+ }
+
+ skeleton->animations.push_back(anim);
+
+ DefaultLogger::get()->debug(Formatter::format() << " " << anim->name << " (" << anim->length << " sec, " << anim->tracks.size() << " tracks)");
+}
+
+void OgreBinarySerializer::ReadSkeletonAnimationTrack(Skeleton *skeleton, Animation *dest)
+{
+ uint16_t boneId = Read<uint16_t>();
+ Bone *bone = dest->parentSkeleton->BoneById(boneId);
+ if (!bone) {
+ throw DeadlyImportError(Formatter::format() << "Cannot read animation track, target bone " << boneId << " not in target Skeleton");
+ }
+
+ VertexAnimationTrack track;
+ track.type = VertexAnimationTrack::VAT_TRANSFORM;
+ track.boneName = bone->name;
+
+ uint16_t id = ReadHeader();
+ while (!AtEnd() && id == SKELETON_ANIMATION_TRACK_KEYFRAME)
+ {
+ ReadSkeletonAnimationKeyFrame(&track);
+
+ if (!AtEnd())
+ id = ReadHeader();
+ }
+ if (!AtEnd())
+ RollbackHeader();
+
+ dest->tracks.push_back(track);
+}
+
+void OgreBinarySerializer::ReadSkeletonAnimationKeyFrame(VertexAnimationTrack *dest)
+{
+ TransformKeyFrame keyframe;
+ keyframe.timePos = Read<float>();
+
+ // Rot and pos
+ ReadQuaternion(keyframe.rotation);
+ ReadVector(keyframe.position);
+
+ // Scale (optional)
+ if (m_currentLen > MSTREAM_KEYFRAME_SIZE_WITHOUT_SCALE)
+ ReadVector(keyframe.scale);
+
+ dest->transformKeyFrames.push_back(keyframe);
+}
+
+void OgreBinarySerializer::ReadSkeletonAnimationLink(Skeleton *skeleton)
+{
+ // Skip bounds, not compatible with Assimp.
+ ReadLine(); // skeleton name
+ SkipBytes(sizeof(float) * 3); // scale
+}
+
+} // Ogre
+} // Assimp
+
+#endif // ASSIMP_BUILD_NO_OGRE_IMPORTER
diff --git a/src/3rdparty/assimp/code/OgreBinarySerializer.h b/src/3rdparty/assimp/code/OgreBinarySerializer.h
new file mode 100644
index 000000000..69db4b722
--- /dev/null
+++ b/src/3rdparty/assimp/code/OgreBinarySerializer.h
@@ -0,0 +1,416 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+
+#ifndef AI_OGREBINARYSERIALIZER_H_INC
+#define AI_OGREBINARYSERIALIZER_H_INC
+
+#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
+
+#include "OgreStructs.h"
+
+namespace Assimp
+{
+namespace Ogre
+{
+
+typedef Assimp::StreamReaderLE MemoryStreamReader;
+typedef boost::shared_ptr<MemoryStreamReader> MemoryStreamReaderPtr;
+
+class OgreBinarySerializer
+{
+public:
+ /// Imports mesh and returns the result.
+ /** @note Fatal unrecoverable errors will throw a DeadlyImportError. */
+ static Mesh *ImportMesh(MemoryStreamReader *reader);
+
+ /// Imports skeleton to @c mesh into Mesh::skeleton.
+ /** If mesh does not have a skeleton reference or the skeleton file
+ cannot be found it is not a fatal DeadlyImportError.
+ @return If skeleton import was successful. */
+ static bool ImportSkeleton(Assimp::IOSystem *pIOHandler, Mesh *mesh);
+ static bool ImportSkeleton(Assimp::IOSystem *pIOHandler, MeshXml *mesh);
+
+private:
+ enum AssetMode
+ {
+ AM_Mesh,
+ AM_Skeleton
+ };
+
+ OgreBinarySerializer(MemoryStreamReader *reader, AssetMode mode) :
+ m_reader(reader),
+ m_currentLen(0),
+ assetMode(mode)
+ {
+ }
+
+ static MemoryStreamReaderPtr OpenReader(Assimp::IOSystem *pIOHandler, const std::string &filename);
+
+ // Header
+
+ uint16_t ReadHeader(bool readLen = true);
+ void RollbackHeader();
+
+ // Mesh
+
+ void ReadMesh(Mesh *mesh);
+ void ReadMeshLodInfo(Mesh *mesh);
+ void ReadMeshSkeletonLink(Mesh *mesh);
+ void ReadMeshBounds(Mesh *mesh);
+ void ReadMeshExtremes(Mesh *mesh);
+
+ void ReadSubMesh(Mesh *mesh);
+ void ReadSubMeshNames(Mesh *mesh);
+ void ReadSubMeshOperation(SubMesh *submesh);
+ void ReadSubMeshTextureAlias(SubMesh *submesh);
+
+ void ReadBoneAssignment(VertexData *dest);
+
+ void ReadGeometry(VertexData *dest);
+ void ReadGeometryVertexDeclaration(VertexData *dest);
+ void ReadGeometryVertexElement(VertexData *dest);
+ void ReadGeometryVertexBuffer(VertexData *dest);
+
+ void ReadEdgeList(Mesh *mesh);
+ void ReadPoses(Mesh *mesh);
+ void ReadPoseVertices(Pose *pose);
+
+ void ReadAnimations(Mesh *mesh);
+ void ReadAnimation(Animation *anim);
+ void ReadAnimationKeyFrames(Animation *anim, VertexAnimationTrack *track);
+
+ void NormalizeBoneWeights(VertexData *vertexData) const;
+
+ // Skeleton
+
+ void ReadSkeleton(Skeleton *skeleton);
+
+ void ReadBone(Skeleton *skeleton);
+ void ReadBoneParent(Skeleton *skeleton);
+
+ void ReadSkeletonAnimation(Skeleton *skeleton);
+ void ReadSkeletonAnimationTrack(Skeleton *skeleton, Animation *dest);
+ void ReadSkeletonAnimationKeyFrame(VertexAnimationTrack *dest);
+ void ReadSkeletonAnimationLink(Skeleton *skeleton);
+
+ // Reader utils
+ bool AtEnd() const;
+
+ template<typename T>
+ inline T Read();
+
+ void ReadBytes(char *dest, size_t numBytes);
+ void ReadBytes(uint8_t *dest, size_t numBytes);
+ void ReadBytes(void *dest, size_t numBytes);
+ uint8_t *ReadBytes(size_t numBytes);
+
+ void ReadVector(aiVector3D &vec);
+ void ReadQuaternion(aiQuaternion &quat);
+
+ std::string ReadString(size_t len);
+ std::string ReadLine();
+
+ void SkipBytes(size_t numBytes);
+
+ uint32_t m_currentLen;
+ MemoryStreamReader *m_reader;
+
+ AssetMode assetMode;
+};
+
+enum MeshChunkId
+{
+ M_HEADER = 0x1000,
+ // char* version : Version number check
+ M_MESH = 0x3000,
+ // bool skeletallyAnimated // important flag which affects h/w buffer policies
+ // Optional M_GEOMETRY chunk
+ M_SUBMESH = 0x4000,
+ // char* materialName
+ // bool useSharedVertices
+ // unsigned int indexCount
+ // bool indexes32Bit
+ // unsigned int* faceVertexIndices (indexCount)
+ // OR
+ // unsigned short* faceVertexIndices (indexCount)
+ // M_GEOMETRY chunk (Optional: present only if useSharedVertices = false)
+ M_SUBMESH_OPERATION = 0x4010, // optional, trilist assumed if missing
+ // unsigned short operationType
+ M_SUBMESH_BONE_ASSIGNMENT = 0x4100,
+ // Optional bone weights (repeating section)
+ // unsigned int vertexIndex;
+ // unsigned short boneIndex;
+ // float weight;
+ // Optional chunk that matches a texture name to an alias
+ // a texture alias is sent to the submesh material to use this texture name
+ // instead of the one in the texture unit with a matching alias name
+ M_SUBMESH_TEXTURE_ALIAS = 0x4200, // Repeating section
+ // char* aliasName;
+ // char* textureName;
+
+ M_GEOMETRY = 0x5000, // NB this chunk is embedded within M_MESH and M_SUBMESH
+ // unsigned int vertexCount
+ M_GEOMETRY_VERTEX_DECLARATION = 0x5100,
+ M_GEOMETRY_VERTEX_ELEMENT = 0x5110, // Repeating section
+ // unsigned short source; // buffer bind source
+ // unsigned short type; // VertexElementType
+ // unsigned short semantic; // VertexElementSemantic
+ // unsigned short offset; // start offset in buffer in bytes
+ // unsigned short index; // index of the semantic (for colours and texture coords)
+ M_GEOMETRY_VERTEX_BUFFER = 0x5200, // Repeating section
+ // unsigned short bindIndex; // Index to bind this buffer to
+ // unsigned short vertexSize; // Per-vertex size, must agree with declaration at this index
+ M_GEOMETRY_VERTEX_BUFFER_DATA = 0x5210,
+ // raw buffer data
+ M_MESH_SKELETON_LINK = 0x6000,
+ // Optional link to skeleton
+ // char* skeletonName : name of .skeleton to use
+ M_MESH_BONE_ASSIGNMENT = 0x7000,
+ // Optional bone weights (repeating section)
+ // unsigned int vertexIndex;
+ // unsigned short boneIndex;
+ // float weight;
+ M_MESH_LOD = 0x8000,
+ // Optional LOD information
+ // string strategyName;
+ // unsigned short numLevels;
+ // bool manual; (true for manual alternate meshes, false for generated)
+ M_MESH_LOD_USAGE = 0x8100,
+ // Repeating section, ordered in increasing depth
+ // NB LOD 0 (full detail from 0 depth) is omitted
+ // LOD value - this is a distance, a pixel count etc, based on strategy
+ // float lodValue;
+ M_MESH_LOD_MANUAL = 0x8110,
+ // Required if M_MESH_LOD section manual = true
+ // String manualMeshName;
+ M_MESH_LOD_GENERATED = 0x8120,
+ // Required if M_MESH_LOD section manual = false
+ // Repeating section (1 per submesh)
+ // unsigned int indexCount;
+ // bool indexes32Bit
+ // unsigned short* faceIndexes; (indexCount)
+ // OR
+ // unsigned int* faceIndexes; (indexCount)
+ M_MESH_BOUNDS = 0x9000,
+ // float minx, miny, minz
+ // float maxx, maxy, maxz
+ // float radius
+
+ // Added By DrEvil
+ // optional chunk that contains a table of submesh indexes and the names of
+ // the sub-meshes.
+ M_SUBMESH_NAME_TABLE = 0xA000,
+ // Subchunks of the name table. Each chunk contains an index & string
+ M_SUBMESH_NAME_TABLE_ELEMENT = 0xA100,
+ // short index
+ // char* name
+ // Optional chunk which stores precomputed edge data
+ M_EDGE_LISTS = 0xB000,
+ // Each LOD has a separate edge list
+ M_EDGE_LIST_LOD = 0xB100,
+ // unsigned short lodIndex
+ // bool isManual // If manual, no edge data here, loaded from manual mesh
+ // bool isClosed
+ // unsigned long numTriangles
+ // unsigned long numEdgeGroups
+ // Triangle* triangleList
+ // unsigned long indexSet
+ // unsigned long vertexSet
+ // unsigned long vertIndex[3]
+ // unsigned long sharedVertIndex[3]
+ // float normal[4]
+
+ M_EDGE_GROUP = 0xB110,
+ // unsigned long vertexSet
+ // unsigned long triStart
+ // unsigned long triCount
+ // unsigned long numEdges
+ // Edge* edgeList
+ // unsigned long triIndex[2]
+ // unsigned long vertIndex[2]
+ // unsigned long sharedVertIndex[2]
+ // bool degenerate
+ // Optional poses section, referred to by pose keyframes
+ M_POSES = 0xC000,
+ M_POSE = 0xC100,
+ // char* name (may be blank)
+ // unsigned short target // 0 for shared geometry,
+ // 1+ for submesh index + 1
+ // bool includesNormals [1.8+]
+ M_POSE_VERTEX = 0xC111,
+ // unsigned long vertexIndex
+ // float xoffset, yoffset, zoffset
+ // float xnormal, ynormal, znormal (optional, 1.8+)
+ // Optional vertex animation chunk
+ M_ANIMATIONS = 0xD000,
+ M_ANIMATION = 0xD100,
+ // char* name
+ // float length
+ M_ANIMATION_BASEINFO = 0xD105,
+ // [Optional] base keyframe information (pose animation only)
+ // char* baseAnimationName (blank for self)
+ // float baseKeyFrameTime
+ M_ANIMATION_TRACK = 0xD110,
+ // unsigned short type // 1 == morph, 2 == pose
+ // unsigned short target // 0 for shared geometry,
+ // 1+ for submesh index + 1
+ M_ANIMATION_MORPH_KEYFRAME = 0xD111,
+ // float time
+ // bool includesNormals [1.8+]
+ // float x,y,z // repeat by number of vertices in original geometry
+ M_ANIMATION_POSE_KEYFRAME = 0xD112,
+ // float time
+ M_ANIMATION_POSE_REF = 0xD113, // repeat for number of referenced poses
+ // unsigned short poseIndex
+ // float influence
+ // Optional submesh extreme vertex list chink
+ M_TABLE_EXTREMES = 0xE000,
+ // unsigned short submesh_index;
+ // float extremes [n_extremes][3];
+};
+
+static std::string MeshHeaderToString(MeshChunkId id)
+{
+ switch(id)
+ {
+ case M_HEADER: return "HEADER";
+ case M_MESH: return "MESH";
+ case M_SUBMESH: return "SUBMESH";
+ case M_SUBMESH_OPERATION: return "SUBMESH_OPERATION";
+ case M_SUBMESH_BONE_ASSIGNMENT: return "SUBMESH_BONE_ASSIGNMENT";
+ case M_SUBMESH_TEXTURE_ALIAS: return "SUBMESH_TEXTURE_ALIAS";
+ case M_GEOMETRY: return "GEOMETRY";
+ case M_GEOMETRY_VERTEX_DECLARATION: return "GEOMETRY_VERTEX_DECLARATION";
+ case M_GEOMETRY_VERTEX_ELEMENT: return "GEOMETRY_VERTEX_ELEMENT";
+ case M_GEOMETRY_VERTEX_BUFFER: return "GEOMETRY_VERTEX_BUFFER";
+ case M_GEOMETRY_VERTEX_BUFFER_DATA: return "GEOMETRY_VERTEX_BUFFER_DATA";
+ case M_MESH_SKELETON_LINK: return "MESH_SKELETON_LINK";
+ case M_MESH_BONE_ASSIGNMENT: return "MESH_BONE_ASSIGNMENT";
+ case M_MESH_LOD: return "MESH_LOD";
+ case M_MESH_LOD_USAGE: return "MESH_LOD_USAGE";
+ case M_MESH_LOD_MANUAL: return "MESH_LOD_MANUAL";
+ case M_MESH_LOD_GENERATED: return "MESH_LOD_GENERATED";
+ case M_MESH_BOUNDS: return "MESH_BOUNDS";
+ case M_SUBMESH_NAME_TABLE: return "SUBMESH_NAME_TABLE";
+ case M_SUBMESH_NAME_TABLE_ELEMENT: return "SUBMESH_NAME_TABLE_ELEMENT";
+ case M_EDGE_LISTS: return "EDGE_LISTS";
+ case M_EDGE_LIST_LOD: return "EDGE_LIST_LOD";
+ case M_EDGE_GROUP: return "EDGE_GROUP";
+ case M_POSES: return "POSES";
+ case M_POSE: return "POSE";
+ case M_POSE_VERTEX: return "POSE_VERTEX";
+ case M_ANIMATIONS: return "ANIMATIONS";
+ case M_ANIMATION: return "ANIMATION";
+ case M_ANIMATION_BASEINFO: return "ANIMATION_BASEINFO";
+ case M_ANIMATION_TRACK: return "ANIMATION_TRACK";
+ case M_ANIMATION_MORPH_KEYFRAME: return "ANIMATION_MORPH_KEYFRAME";
+ case M_ANIMATION_POSE_KEYFRAME: return "ANIMATION_POSE_KEYFRAME";
+ case M_ANIMATION_POSE_REF: return "ANIMATION_POSE_REF";
+ case M_TABLE_EXTREMES: return "TABLE_EXTREMES";
+ }
+ return "Unknown_MeshChunkId";
+}
+
+enum SkeletonChunkId
+{
+ SKELETON_HEADER = 0x1000,
+ // char* version : Version number check
+ SKELETON_BLENDMODE = 0x1010, // optional
+ // unsigned short blendmode : SkeletonAnimationBlendMode
+ SKELETON_BONE = 0x2000,
+ // Repeating section defining each bone in the system.
+ // Bones are assigned indexes automatically based on their order of declaration
+ // starting with 0.
+ // char* name : name of the bone
+ // unsigned short handle : handle of the bone, should be contiguous & start at 0
+ // Vector3 position : position of this bone relative to parent
+ // Quaternion orientation : orientation of this bone relative to parent
+ // Vector3 scale : scale of this bone relative to parent
+ SKELETON_BONE_PARENT = 0x3000,
+ // Record of the parent of a single bone, used to build the node tree
+ // Repeating section, listed in Bone Index order, one per Bone
+ // unsigned short handle : child bone
+ // unsigned short parentHandle : parent bone
+ SKELETON_ANIMATION = 0x4000,
+ // A single animation for this skeleton
+ // char* name : Name of the animation
+ // float length : Length of the animation in seconds
+ SKELETON_ANIMATION_BASEINFO = 0x4010,
+ // [Optional] base keyframe information
+ // char* baseAnimationName (blank for self)
+ // float baseKeyFrameTime
+ SKELETON_ANIMATION_TRACK = 0x4100,
+ // A single animation track (relates to a single bone)
+ // Repeating section (within SKELETON_ANIMATION)
+ // unsigned short boneIndex : Index of bone to apply to
+ SKELETON_ANIMATION_TRACK_KEYFRAME = 0x4110,
+ // A single keyframe within the track
+ // Repeating section
+ // float time : The time position (seconds)
+ // Quaternion rotate : Rotation to apply at this keyframe
+ // Vector3 translate : Translation to apply at this keyframe
+ // Vector3 scale : Scale to apply at this keyframe
+ SKELETON_ANIMATION_LINK = 0x5000
+ // Link to another skeleton, to re-use its animations
+ // char* skeletonName : name of skeleton to get animations from
+ // float scale : scale to apply to trans/scale keys
+};
+
+static std::string SkeletonHeaderToString(SkeletonChunkId id)
+{
+ switch(id)
+ {
+ case SKELETON_HEADER: return "HEADER";
+ case SKELETON_BLENDMODE: return "BLENDMODE";
+ case SKELETON_BONE: return "BONE";
+ case SKELETON_BONE_PARENT: return "BONE_PARENT";
+ case SKELETON_ANIMATION: return "ANIMATION";
+ case SKELETON_ANIMATION_BASEINFO: return "ANIMATION_BASEINFO";
+ case SKELETON_ANIMATION_TRACK: return "ANIMATION_TRACK";
+ case SKELETON_ANIMATION_TRACK_KEYFRAME: return "ANIMATION_TRACK_KEYFRAME";
+ case SKELETON_ANIMATION_LINK: return "ANIMATION_LINK";
+ }
+ return "Unknown_SkeletonChunkId";
+}
+} // Ogre
+} // Assimp
+
+#endif // ASSIMP_BUILD_NO_OGRE_IMPORTER
+#endif // AI_OGREBINARYSERIALIZER_H_INC
diff --git a/src/3rdparty/assimp/code/OgreImporter.cpp b/src/3rdparty/assimp/code/OgreImporter.cpp
index 94c7701ba..1760fceea 100644
--- a/src/3rdparty/assimp/code/OgreImporter.cpp
+++ b/src/3rdparty/assimp/code/OgreImporter.cpp
@@ -38,32 +38,27 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
-#include "AssimpPCH.h"
-
#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
-#include <vector>
-#include <sstream>
+#include "AssimpPCH.h"
#include "OgreImporter.h"
-#include "TinyFormatter.h"
-#include "irrXMLWrapper.h"
+#include "OgreBinarySerializer.h"
+#include "OgreXmlSerializer.h"
static const aiImporterDesc desc = {
- "Ogre XML Mesh Importer",
+ "Ogre3D Mesh Importer",
"",
"",
"",
- aiImporterFlags_SupportTextFlavour,
+ aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour,
0,
0,
0,
0,
- "mesh.xml"
+ "mesh mesh.xml"
};
-using namespace std;
-
namespace Assimp
{
namespace Ogre
@@ -83,174 +78,67 @@ void OgreImporter::SetupProperties(const Importer* pImp)
bool OgreImporter::CanRead(const std::string &pFile, Assimp::IOSystem *pIOHandler, bool checkSig) const
{
if (!checkSig) {
- return EndsWith(pFile, ".mesh.xml", false);
+ return EndsWith(pFile, ".mesh.xml", false) || EndsWith(pFile, ".mesh", false);
}
- const char* tokens[] = { "<mesh>" };
- return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
+ if (EndsWith(pFile, ".mesh.xml", false))
+ {
+ const char* tokens[] = { "<mesh>" };
+ return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
+ }
+ else
+ {
+ /// @todo Read and validate first header chunk?
+ return EndsWith(pFile, ".mesh", false);
+ }
}
void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Assimp::IOSystem *pIOHandler)
{
- // -------------------- Initial file and XML operations --------------------
-
- // Open
- boost::scoped_ptr<IOStream> file(pIOHandler->Open(pFile));
- if (!file.get()) {
+ // Open source file
+ IOStream *f = pIOHandler->Open(pFile, "rb");
+ if (!f) {
throw DeadlyImportError("Failed to open file " + pFile);
}
- // Read
- boost::scoped_ptr<CIrrXML_IOStreamReader> xmlStream(new CIrrXML_IOStreamReader(file.get()));
- boost::scoped_ptr<XmlReader> reader(irr::io::createIrrXMLReader(xmlStream.get()));
- if (!reader) {
- throw DeadlyImportError("Failed to create XML Reader for " + pFile);
- }
-
- DefaultLogger::get()->debug("Opened a XML reader for " + pFile);
-
- // Read root node
- NextNode(reader.get());
- if (!CurrentNodeNameEquals(reader.get(), "mesh")) {
- throw DeadlyImportError("Root node is not <mesh> but <" + string(reader->getNodeName()) + "> in " + pFile);
- }
-
- // Node names
- const string nnSharedGeometry = "sharedgeometry";
- const string nnVertexBuffer = "vertexbuffer";
- const string nnSubMeshes = "submeshes";
- const string nnSubMesh = "submesh";
- const string nnSubMeshNames = "submeshnames";
- const string nnSkeletonLink = "skeletonlink";
-
- // -------------------- Shared Geometry --------------------
- // This can be used to share geometry between submeshes
-
- NextNode(reader.get());
- if (CurrentNodeNameEquals(reader.get(), nnSharedGeometry))
- {
- DefaultLogger::get()->debug("Reading shared geometry");
- unsigned int NumVertices = GetAttribute<unsigned int>(reader.get(), "vertexcount");
-
- NextNode(reader.get());
- while(CurrentNodeNameEquals(reader.get(), nnVertexBuffer)) {
- ReadVertexBuffer(m_SharedGeometry, reader.get(), NumVertices);
- }
- }
-
- // -------------------- Sub Meshes --------------------
-
- if (!CurrentNodeNameEquals(reader.get(), nnSubMeshes)) {
- throw DeadlyImportError("Could not find <submeshes> node inside root <mesh> node");
- }
-
- vector<boost::shared_ptr<SubMesh> > subMeshes;
- vector<aiMaterial*> materials;
-
- NextNode(reader.get());
- while(CurrentNodeNameEquals(reader.get(), nnSubMesh))
+ // Binary .mesh import
+ if (EndsWith(pFile, ".mesh", false))
{
- SubMesh* submesh = new SubMesh();
- ReadSubMesh(subMeshes.size(), *submesh, reader.get());
+ /// @note MemoryStreamReader takes ownership of f.
+ MemoryStreamReader reader(f);
- // Just a index in a array, we add a mesh in each loop cycle, so we get indicies like 0, 1, 2 ... n;
- // so it is important to do this before pushing the mesh in the vector!
- /// @todo Not sure if this really is needed, refactor out if possible.
- submesh->MaterialIndex = subMeshes.size();
+ // Import mesh
+ boost::scoped_ptr<Mesh> mesh(OgreBinarySerializer::ImportMesh(&reader));
- subMeshes.push_back(boost::shared_ptr<SubMesh>(submesh));
+ // Import skeleton
+ OgreBinarySerializer::ImportSkeleton(pIOHandler, mesh.get());
- /** @todo What is the correct way of handling empty ref here.
- Does Assimp require there to be a valid material index for each mesh,
- even if its a dummy material. */
- aiMaterial* material = ReadMaterial(pFile, pIOHandler, submesh->MaterialName);
- materials.push_back(material);
- }
+ // Import mesh referenced materials
+ ReadMaterials(pFile, pIOHandler, pScene, mesh.get());
- if (subMeshes.empty()) {
- throw DeadlyImportError("Could not find <submeshes> node inside root <mesh> node");
- }
-
- // This is really a internal error if we failed to create dummy materials.
- if (subMeshes.size() != materials.size()) {
- throw DeadlyImportError("Internal Error: Material count does not match the submesh count");
- }
-
- // Skip submesh names.
- /// @todo Should these be read to scene etc. metadata?
- if (CurrentNodeNameEquals(reader.get(), nnSubMeshNames))
- {
- NextNode(reader.get());
- while(CurrentNodeNameEquals(reader.get(), nnSubMesh)) {
- NextNode(reader.get());
- }
- }
-
- // -------------------- Skeleton --------------------
-
- vector<Bone> Bones;
- vector<Animation> Animations;
-
- if (CurrentNodeNameEquals(reader.get(), nnSkeletonLink))
- {
- string skeletonFile = GetAttribute<string>(reader.get(), "name");
- if (!skeletonFile.empty())
- {
- ReadSkeleton(pFile, pIOHandler, pScene, skeletonFile, Bones, Animations);
- }
- else
- {
- DefaultLogger::get()->debug("Found a unusual <" + nnSkeletonLink + "> with a empty file reference");
- }
- NextNode(reader.get());
+ // Convert to Assimp
+ mesh->ConvertToAssimpScene(pScene);
}
+ // XML .mesh.xml import
else
{
- DefaultLogger::get()->debug("Mesh has no assigned skeleton with <" + nnSkeletonLink + ">");
- }
+ /// @note XmlReader does not take ownership of f, hence the scoped ptr.
+ boost::scoped_ptr<IOStream> scopedFile(f);
+ boost::scoped_ptr<CIrrXML_IOStreamReader> xmlStream(new CIrrXML_IOStreamReader(scopedFile.get()));
+ boost::scoped_ptr<XmlReader> reader(irr::io::createIrrXMLReader(xmlStream.get()));
- // Now there might be <boneassignments> for the shared geometry
- if (CurrentNodeNameEquals(reader.get(), "boneassignments")) {
- ReadBoneWeights(m_SharedGeometry, reader.get());
- }
+ // Import mesh
+ boost::scoped_ptr<MeshXml> mesh(OgreXmlSerializer::ImportMesh(reader.get()));
+
+ // Import skeleton
+ OgreXmlSerializer::ImportSkeleton(pIOHandler, mesh.get());
- // -------------------- Process Results --------------------
- BOOST_FOREACH(boost::shared_ptr<SubMesh> submesh, subMeshes)
- {
- ProcessSubMesh(*submesh.get(), m_SharedGeometry);
- }
-
- // -------------------- Apply to aiScene --------------------
+ // Import mesh referenced materials
+ ReadMaterials(pFile, pIOHandler, pScene, mesh.get());
- // Materials
- pScene->mMaterials = new aiMaterial*[materials.size()];
- pScene->mNumMaterials = materials.size();
-
- for(size_t i=0, len=materials.size(); i<len; ++i) {
- pScene->mMaterials[i] = materials[i];
+ // Convert to Assimp
+ mesh->ConvertToAssimpScene(pScene);
}
-
- // Meshes
- pScene->mMeshes = new aiMesh*[subMeshes.size()];
- pScene->mNumMeshes = subMeshes.size();
-
- for(size_t i=0, len=subMeshes.size(); i<len; ++i)
- {
- boost::shared_ptr<SubMesh> submesh = subMeshes[i];
- pScene->mMeshes[i] = CreateAssimpSubMesh(pScene, *(submesh.get()), Bones);
- }
-
- // Create the root node
- pScene->mRootNode = new aiNode();
- pScene->mRootNode->mMeshes = new unsigned int[subMeshes.size()];
- pScene->mRootNode->mNumMeshes = subMeshes.size();
-
- for(size_t i=0, len=subMeshes.size(); i<len; ++i) {
- pScene->mRootNode->mMeshes[i] = static_cast<unsigned int>(i);
- }
-
- // Skeleton and animations
- CreateAssimpSkeleton(pScene, Bones, Animations);
}
} // Ogre
diff --git a/src/3rdparty/assimp/code/OgreImporter.h b/src/3rdparty/assimp/code/OgreImporter.h
index f43398751..2d9cf971e 100644
--- a/src/3rdparty/assimp/code/OgreImporter.h
+++ b/src/3rdparty/assimp/code/OgreImporter.h
@@ -1,3 +1,42 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
#ifndef AI_OGREIMPORTER_H_INC
#define AI_OGREIMPORTER_H_INC
@@ -5,6 +44,8 @@
#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
#include "BaseImporter.h"
+
+#include "OgreStructs.h"
#include "OgreParsingUtils.h"
namespace Assimp
@@ -12,58 +53,10 @@ namespace Assimp
namespace Ogre
{
-struct Face;
-struct BoneWeight;
-struct Bone;
-struct Animation;
-
-/// Ogre SubMesh
-struct SubMesh
-{
- bool UseSharedGeometry;
- bool Use32bitIndexes;
-
- std::string Name;
- std::string MaterialName;
-
- bool HasGeometry;
- bool HasPositions;
- bool HasNormals;
- bool HasTangents;
-
- std::vector<Face> Faces;
- std::vector<aiVector3D> Positions;
- std::vector<aiVector3D> Normals;
- std::vector<aiVector3D> Tangents;
-
- /// Arbitrary number of texcoords, they are nearly always 2d, but Assimp has always 3d texcoords, n vectors(outer) with texcoords for each vertex(inner).
- std::vector<std::vector<aiVector3D> > Uvs;
-
- /// A list(inner) of bones for each vertex(outer).
- std::vector<std::vector<BoneWeight> > Weights;
-
- /// The Index in the Assimp material array from the material witch is attached to this submesh.
- int MaterialIndex;
-
- // The highest index of a bone from a bone weight, this is needed to create the Assimp bone struct. Converting from vertex-bones to bone-vertices.
- unsigned int BonesUsed;
-
- SubMesh() :
- UseSharedGeometry(false),
- Use32bitIndexes(false),
- HasGeometry(false),
- HasPositions(false),
- HasNormals(false),
- HasTangents(false),
- MaterialIndex(-1),
- BonesUsed(0)
- {
- }
-};
-
/** Importer for Ogre mesh, skeleton and material formats.
- @todo Support vertex colors
- @todo Support multiple TexCoords (this is already done??) */
+ @todo Support vertex colors.
+ @todo Support poses/animations from the mesh file.
+ Currently only skeleton file animations are supported. */
class OgreImporter : public BaseImporter
{
public:
@@ -80,40 +73,11 @@ public:
virtual void SetupProperties(const Importer *pImp);
private:
- //-------------------------------- OgreMesh.cpp -------------------------------
-
- /// Helper Functions to read parts of the XML File.
- void ReadSubMesh(const unsigned int submeshIndex, SubMesh &submesh, XmlReader *reader);
-
- /// Reads a single Vertexbuffer and writes its data in the Submesh.
- static void ReadVertexBuffer(SubMesh &submesh, XmlReader *reader, const unsigned int numVertices);
-
- /// Reads bone weights are stores them into the given submesh.
- static void ReadBoneWeights(SubMesh &submesh, XmlReader *reader);
-
- /// After Loading a SubMehs some work needs to be done (make all Vertexes unique, normalize weights).
- static void ProcessSubMesh(SubMesh &submesh, SubMesh &sharedGeometry);
-
- /// Uses the bone data to convert a SubMesh into a aiMesh which will be created and returned.
- aiMesh *CreateAssimpSubMesh(aiScene *pScene, const SubMesh &submesh, const std::vector<Bone> &bones) const;
-
- //-------------------------------- OgreSkeleton.cpp -------------------------------
-
- /// Writes the results in Bones and Animations, Filename is not const, because its call-by-value and the function will change it!
- void ReadSkeleton(const std::string &pFile, Assimp::IOSystem *pIOHandler, const aiScene *pScene,
- const std::string &skeletonFile, std::vector<Bone> &Bones, std::vector<Animation> &Animations) const;
-
- /// Converts the animations in aiAnimations and puts them into the scene.
- void PutAnimationsInScene(aiScene *pScene, const std::vector<Bone> &Bones, const std::vector<Animation> &Animations);
-
- /// Creates the aiSkeleton in current scene.
- void CreateAssimpSkeleton(aiScene *pScene, const std::vector<Bone> &bones, const std::vector<Animation> &animations);
-
- /// Recursively creates a filled aiNode from a given root bone.
- static aiNode* CreateNodeFromBone(int boneId, const std::vector<Bone> &bones, aiNode *parent);
-
- //-------------------------------- OgreMaterial.cpp -------------------------------
-
+ /// Read materials referenced by the @c mesh to @c pScene.
+ void ReadMaterials(const std::string &pFile, Assimp::IOSystem *pIOHandler, aiScene *pScene, Mesh *mesh);
+ void ReadMaterials(const std::string &pFile, Assimp::IOSystem *pIOHandler, aiScene *pScene, MeshXml *mesh);
+ void AssignMaterials(aiScene *pScene, std::vector<aiMaterial*> &materials);
+
/// Reads material
aiMaterial* ReadMaterial(const std::string &pFile, Assimp::IOSystem *pIOHandler, const std::string MaterialName);
@@ -125,104 +89,8 @@ private:
std::string m_userDefinedMaterialLibFile;
bool m_detectTextureTypeFromFilename;
- /// VertexBuffer for the sub meshes that use shader geometry.
- SubMesh m_SharedGeometry;
-
std::map<aiTextureType, unsigned int> m_textures;
};
-
-/// Simplified face.
-/** @todo Support other polygon types than just just triangles. Move to using aiFace. */
-struct Face
-{
- unsigned int VertexIndices[3];
-};
-
-/// Ogre Bone assignment
-struct BoneAssignment
-{
- /// Bone ID from Ogre.
- unsigned int BoneId;
- // Bone name for Assimp.
- std::string BoneName;
-};
-
-/// Ogre Bone weight
-struct BoneWeight
-{
- /// Bone Id
- unsigned int Id;
- /// BoneWeight
- float Value;
-};
-
-
-/// Ogre Bone
-struct Bone
-{
- std::string Name;
-
- int Id;
- int ParentId;
-
- aiVector3D Position;
- aiVector3D RotationAxis;
- float RotationAngle;
-
- aiMatrix4x4 BoneToWorldSpace;
-
- std::vector<int> Children;
-
- Bone() :
- Id(-1),
- ParentId(-1),
- RotationAngle(0.0f)
- {
- }
-
- /// Returns if this bone is parented.
- bool IsParented() const { return (ParentId != -1); }
-
- /// This operator is needed to sort the bones by Id in a vector<Bone>.
- bool operator<(const Bone &other) const { return (Id < other.Id); }
-
- /// This operator is needed to find a bone by its name in a vector<Bone>
- bool operator==(const std::string& other) const { return Name == other; }
- bool operator==(const aiString& other) const { return Name == std::string(other.data); }
-
- /// @note Implemented in OgreSkeleton.cpp
- void CalculateBoneToWorldSpaceMatrix(std::vector<Bone>& Bones);
-};
-
-/// Ogre animation key frame
-/** Transformations for a frame. */
-struct KeyFrame
-{
- float Time;
- aiVector3D Position;
- aiQuaternion Rotation;
- aiVector3D Scaling;
-};
-
-/// Ogre animation track
-/** Keyframes for one bone. */
-struct Track
-{
- std::string BoneName;
- std::vector<KeyFrame> Keyframes;
-};
-
-/// Ogre animation
-struct Animation
-{
- /// Name
- std::string Name;
- /// Length
- float Length;
- /// Tracks
- std::vector<Track> Tracks;
-};
-
} // Ogre
} // Assimp
diff --git a/src/3rdparty/assimp/code/OgreImporter.hpp b/src/3rdparty/assimp/code/OgreImporter.hpp
deleted file mode 100644
index a24d1fc3f..000000000
--- a/src/3rdparty/assimp/code/OgreImporter.hpp
+++ /dev/null
@@ -1,185 +0,0 @@
-#include "BaseImporter.h"
-
-#include <vector>
-
-#include "OgreXmlHelper.hpp"
-#include "irrXMLWrapper.h"
-
-/// Ogre Importer TODO
-/* - Read Vertex Colors
- - Read multiple TexCoords
-*/
-
-
-
-namespace Assimp
-{
-namespace Ogre
-{
-
-
-//Forward declarations:
-struct Face;
-struct Weight;
-struct Bone;
-struct Animation;
-struct Track;
-struct Keyframe;
-
-///A submesh from Ogre
-struct SubMesh
-{
- bool SharedData;
-
- std::string Name;
- std::string MaterialName;
- std::vector<Face> FaceList;
-
- std::vector<aiVector3D> Positions; bool HasPositions;
- std::vector<aiVector3D> Normals; bool HasNormals;
- std::vector<aiVector3D> Tangents; bool HasTangents;
- std::vector<std::vector<aiVector3D> > Uvs;//arbitrary number of texcoords, they are nearly always 2d, but assimp has always 3d texcoords, n vectors(outer) with texcoords for each vertex(inner)
-
- std::vector< std::vector<Weight> > Weights;//a list(inner) of bones for each vertex(outer)
- int MaterialIndex;///< The Index in the Assimp Materialarray from the material witch is attached to this submesh
- unsigned int BonesUsed;//the highest index of a bone from a bone weight, this is needed to create the assimp bone structur (converting from Vertex-Bones to Bone-Vertices)
-
- SubMesh(): SharedData(false), HasPositions(false), HasNormals(false), HasTangents(false),
- MaterialIndex(-1), BonesUsed(0) {}//initialize everything
-};
-
-
-///The Main Ogre Importer Class
-class OgreImporter : public BaseImporter
-{
-public:
- virtual bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const;
- virtual void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
- virtual const aiImporterDesc* GetInfo () const;
- virtual void SetupProperties(const Importer* pImp);
-private:
-
-
- //-------------------------------- OgreMesh.cpp -------------------------------
- /// Helper Functions to read parts of the XML File
- void ReadSubMesh(SubMesh& theSubMesh, XmlReader* Reader);//the submesh reference is the result value
-
- /// Reads a single Vertexbuffer and writes its data in the Submesh
- static void ReadVertexBuffer(SubMesh &theSubMesh, XmlReader *Reader, unsigned int NumVertices);
-
- /// Reads bone weights are stores them into the given submesh
- static void ReadBoneWeights(SubMesh &theSubMesh, XmlReader *Reader);
-
- /// After Loading a SubMehs some work needs to be done (make all Vertexes unique, normalize weights)
- static void ProcessSubMesh(SubMesh &theSubMesh, SubMesh &theSharedGeometry);
-
- /// Uses the bone data to convert a SubMesh into a aiMesh which will be created and returned
- aiMesh* CreateAssimpSubMesh(const SubMesh &theSubMesh, const std::vector<Bone>& Bones) const;
-
-
- //-------------------------------- OgreSkeleton.cpp -------------------------------
- /// Writes the results in Bones and Animations, Filename is not const, because its call-by-value and the function will change it!
- void LoadSkeleton(std::string FileName, std::vector<Bone> &Bones, std::vector<Animation> &Animations) const;
-
- /// Converts the animations in aiAnimations and puts them into the scene
- void PutAnimationsInScene(const std::vector<Bone> &Bones, const std::vector<Animation> &Animations);
-
- /// Creates the aiskeleton in current scene
- void CreateAssimpSkeleton(const std::vector<Bone> &Bones, const std::vector<Animation> &Animations);
-
- /// Recursivly creates a filled aiNode from a given root bone
- static aiNode* CreateAiNodeFromBone(int BoneId, const std::vector<Bone> &Bones, aiNode* ParentNode);
-
-
- //-------------------------------- OgreMaterial.cpp -------------------------------
- aiMaterial* LoadMaterial(const std::string MaterialName) const;
- void ReadTechnique(std::stringstream &ss, aiMaterial* NewMaterial) const;
-
-
-
-
- //Now we don't have to give theses parameters to all functions
- std::string m_CurrentFilename;
- std::string m_MaterialLibFilename;
- bool m_TextureTypeFromFilename;
- IOSystem* m_CurrentIOHandler;
- aiScene *m_CurrentScene;
- SubMesh m_SharedGeometry;///< we will just use the vertexbuffers of the submesh
-};
-
-///For the moment just triangles, no other polygon types!
-struct Face
-{
- unsigned int VertexIndices[3];
-};
-
-struct BoneAssignment
-{
- unsigned int BoneId;//this is, what we get from ogre
- std::string BoneName;//this is, what we need for assimp
-};
-
-///for a vertex->bone structur
-struct Weight
-{
- unsigned int BoneId;
- float Value;
-};
-
-
-/// Helper Class to describe an ogre-bone for the skeleton:
-/** All Id's are signed ints, because than we have -1 as a simple INVALID_ID Value (we start from 0 so 0 is a valid bone ID!*/
-struct Bone
-{
- int Id;
- int ParentId;
- std::string Name;
- aiVector3D Position;
- float RotationAngle;
- aiVector3D RotationAxis;
- std::vector<int> Children;
- aiMatrix4x4 BoneToWorldSpace;
-
- ///ctor
- Bone(): Id(-1), ParentId(-1), RotationAngle(0.0f) {}
- ///this operator is needed to sort the bones after Id's
- bool operator<(const Bone& rval) const
- {return Id<rval.Id; }
- ///this operator is needed to find a bone by its name in a vector<Bone>
- bool operator==(const std::string& rval) const
- {return Name==rval; }
- bool operator==(const aiString& rval) const
- {return Name==std::string(rval.data); }
-
- // implemented in OgreSkeleton.cpp
- void CalculateBoneToWorldSpaceMatrix(std::vector<Bone>& Bones);
-};
-
-
-
-///Describes an Ogre Animation
-struct Animation
-{
- std::string Name;
- float Length;
- std::vector<Track> Tracks;
-};
-
-///a track (keyframes for one bone) from an animation
-struct Track
-{
- std::string BoneName;
- std::vector<Keyframe> Keyframes;
-};
-
-/// keyframe (bone transformation) from a track from a animation
-struct Keyframe
-{
- float Time;
- aiVector3D Position;
- aiQuaternion Rotation;
- aiVector3D Scaling;
-};
-
-}//namespace Ogre
-}//namespace Assimp
diff --git a/src/3rdparty/assimp/code/OgreMaterial.cpp b/src/3rdparty/assimp/code/OgreMaterial.cpp
index 157af24aa..a85741f18 100644
--- a/src/3rdparty/assimp/code/OgreMaterial.cpp
+++ b/src/3rdparty/assimp/code/OgreMaterial.cpp
@@ -42,12 +42,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
-#include <vector>
-#include <sstream>
-
#include "OgreImporter.h"
#include "TinyFormatter.h"
+#include "fast_atof.h"
+
+#include <vector>
+#include <sstream>
+
using namespace std;
namespace Assimp
@@ -59,11 +61,66 @@ static const string partComment = "//";
static const string partBlockStart = "{";
static const string partBlockEnd = "}";
+void OgreImporter::ReadMaterials(const std::string &pFile, Assimp::IOSystem *pIOHandler, aiScene *pScene, Mesh *mesh)
+{
+ std::vector<aiMaterial*> materials;
+
+ // Create materials that can be found and parsed via the IOSystem.
+ for (size_t i=0, len=mesh->NumSubMeshes(); i<len; ++i)
+ {
+ SubMesh *submesh = mesh->GetSubMesh(i);
+ if (submesh && !submesh->materialRef.empty())
+ {
+ aiMaterial *material = ReadMaterial(pFile, pIOHandler, submesh->materialRef);
+ if (material)
+ {
+ submesh->materialIndex = materials.size();
+ materials.push_back(material);
+ }
+ }
+ }
+
+ AssignMaterials(pScene, materials);
+}
+
+void OgreImporter::ReadMaterials(const std::string &pFile, Assimp::IOSystem *pIOHandler, aiScene *pScene, MeshXml *mesh)
+{
+ std::vector<aiMaterial*> materials;
+
+ // Create materials that can be found and parsed via the IOSystem.
+ for (size_t i=0, len=mesh->NumSubMeshes(); i<len; ++i)
+ {
+ SubMeshXml *submesh = mesh->GetSubMesh(i);
+ if (submesh && !submesh->materialRef.empty())
+ {
+ aiMaterial *material = ReadMaterial(pFile, pIOHandler, submesh->materialRef);
+ if (material)
+ {
+ submesh->materialIndex = materials.size();
+ materials.push_back(material);
+ }
+ }
+ }
+
+ AssignMaterials(pScene, materials);
+}
+
+void OgreImporter::AssignMaterials(aiScene *pScene, std::vector<aiMaterial*> &materials)
+{
+ pScene->mNumMaterials = materials.size();
+ if (pScene->mNumMaterials > 0)
+ {
+ pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
+ for(size_t i=0;i<pScene->mNumMaterials; ++i) {
+ pScene->mMaterials[i] = materials[i];
+ }
+ }
+}
+
aiMaterial* OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSystem *pIOHandler, const std::string materialName)
{
- /// @todo Should we return null ptr here or a empty material?
if (materialName.empty()) {
- return new aiMaterial();
+ return 0;
}
// Full reference and examples of Ogre Material Script
@@ -117,17 +174,15 @@ aiMaterial* OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSyste
}
if (!materialFile)
{
- /// @todo Should we return null ptr here or a empty material?
DefaultLogger::get()->error(Formatter::format() << "Failed to find source file for material '" << materialName << "'");
- return new aiMaterial();
+ return 0;
}
boost::scoped_ptr<IOStream> stream(materialFile);
if (stream->FileSize() == 0)
{
- /// @todo Should we return null ptr here or a empty material?
DefaultLogger::get()->warn(Formatter::format() << "Source file for material '" << materialName << "' is empty (size is 0 bytes)");
- return new aiMaterial();
+ return 0;
}
// Read bytes
@@ -162,8 +217,7 @@ aiMaterial* OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSyste
// Skip commented lines
if (linePart == partComment)
{
- string postComment = NextAfterNewLine(ss, linePart);
- DefaultLogger::get()->debug("//" + postComment + " (comment line ignored)");
+ NextAfterNewLine(ss, linePart);
continue;
}
if (linePart != partMaterial)
@@ -306,8 +360,7 @@ bool OgreImporter::ReadTechnique(const std::string &techniqueName, stringstream
// Skip commented lines
if (linePart == partComment)
{
- string postComment = SkipLine(ss);
- DefaultLogger::get()->debug(" //" + postComment + " (comment line ignored)");
+ SkipLine(ss);
continue;
}
@@ -347,8 +400,7 @@ bool OgreImporter::ReadPass(const std::string &passName, stringstream &ss, aiMat
// Skip commented lines
if (linePart == partComment)
{
- string postComment = SkipLine(ss);
- DefaultLogger::get()->debug(" //" + postComment + " (comment line ignored)");
+ SkipLine(ss);
continue;
}
@@ -416,8 +468,7 @@ bool OgreImporter::ReadTextureUnit(const std::string &textureUnitName, stringstr
// Skip commented lines
if (linePart == partComment)
{
- string postComment = SkipLine(ss);
- DefaultLogger::get()->debug(" //" + postComment + " (comment line ignored)");
+ SkipLine(ss);
continue;
}
diff --git a/src/3rdparty/assimp/code/OgreMesh.cpp b/src/3rdparty/assimp/code/OgreMesh.cpp
deleted file mode 100644
index c25f73b95..000000000
--- a/src/3rdparty/assimp/code/OgreMesh.cpp
+++ /dev/null
@@ -1,569 +0,0 @@
-/*
-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.
-
-----------------------------------------------------------------------
-*/
-
-#include "AssimpPCH.h"
-
-#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
-
-#include "OgreImporter.h"
-#include "TinyFormatter.h"
-
-using namespace std;
-
-namespace Assimp
-{
-namespace Ogre
-{
-
-void OgreImporter::ReadSubMesh(const unsigned int submeshIndex, SubMesh &submesh, XmlReader *reader)
-{
- if (reader->getAttributeValue("material")) {
- submesh.MaterialName = GetAttribute<string>(reader, "material");
- }
- if (reader->getAttributeValue("use32bitindexes")) {
- submesh.Use32bitIndexes = GetAttribute<bool>(reader, "use32bitindexes");
- }
- if (reader->getAttributeValue("usesharedvertices")) {
- submesh.UseSharedGeometry = GetAttribute<bool>(reader, "usesharedvertices");
- }
-
- DefaultLogger::get()->debug(Formatter::format() << "Reading submesh " << submeshIndex);
- DefaultLogger::get()->debug(Formatter::format() << " - Material '" << submesh.MaterialName << "'");
- DefaultLogger::get()->debug(Formatter::format() << " - Shader geometry = " << (submesh.UseSharedGeometry ? "true" : "false") <<
- ", 32bit indexes = " << (submesh.Use32bitIndexes ? "true" : "false"));
-
- //TODO: maybe we have alsways just 1 faces and 1 geometry and always in this order. this loop will only work correct, when the order
- //of faces and geometry changed, and not if we have more than one of one
- /// @todo Fix above comment with better read logic below
-
- NextNode(reader);
- string currentNodeName = reader->getNodeName();
-
- const string nnFaces = "faces";
- const string nnFace = "face";
- const string nnGeometry = "geometry";
- const string nnBoneAssignments = "boneassignments";
- const string nnVertexBuffer = "vertexbuffer";
-
- bool quadWarned = false;
-
- while(currentNodeName == nnFaces ||
- currentNodeName == nnGeometry ||
- currentNodeName == nnBoneAssignments)
- {
- if (currentNodeName == nnFaces)
- {
- unsigned int numFaces = GetAttribute<unsigned int>(reader, "count");
-
- NextNode(reader);
- currentNodeName = reader->getNodeName();
-
- while(currentNodeName == nnFace)
- {
- Face NewFace;
- NewFace.VertexIndices[0] = GetAttribute<int>(reader, "v1");
- NewFace.VertexIndices[1] = GetAttribute<int>(reader, "v2");
- NewFace.VertexIndices[2] = GetAttribute<int>(reader, "v3");
-
- /// @todo Support quads
- if (!quadWarned && reader->getAttributeValue("v4")) {
- DefaultLogger::get()->warn("Submesh has quads, only triangles are supported at the moment!");
- }
-
- submesh.Faces.push_back(NewFace);
-
- // Advance
- NextNode(reader);
- currentNodeName = reader->getNodeName();
- }
-
- if (submesh.Faces.size() == numFaces)
- {
- DefaultLogger::get()->debug(Formatter::format() << " - Faces " << numFaces);
- }
- else
- {
- throw DeadlyImportError(Formatter::format() << "Read only " << submesh.Faces.size() << " faces when should have read " << numFaces);
- }
- }
- else if (currentNodeName == nnGeometry)
- {
- unsigned int numVertices = GetAttribute<int>(reader, "vertexcount");
-
- NextNode(reader);
- while(string(reader->getNodeName()) == nnVertexBuffer) {
- ReadVertexBuffer(submesh, reader, numVertices);
- }
- }
- else if (reader->getNodeName() == nnBoneAssignments)
- {
- ReadBoneWeights(submesh, reader);
- }
-
- currentNodeName = reader->getNodeName();
- }
-}
-
-void OgreImporter::ReadVertexBuffer(SubMesh &submesh, XmlReader *reader, const unsigned int numVertices)
-{
- DefaultLogger::get()->debug(Formatter::format() << "Reading vertex buffer with " << numVertices << " vertices");
-
- submesh.HasGeometry = true;
-
- if (reader->getAttributeValue("positions") && GetAttribute<bool>(reader, "positions"))
- {
- submesh.HasPositions = true;
- submesh.Positions.reserve(numVertices);
- DefaultLogger::get()->debug(" - Has positions");
- }
- if (reader->getAttributeValue("normals") && GetAttribute<bool>(reader, "normals"))
- {
- submesh.HasNormals = true;
- submesh.Normals.reserve(numVertices);
- DefaultLogger::get()->debug(" - Has normals");
- }
- if (reader->getAttributeValue("tangents") && GetAttribute<bool>(reader, "tangents"))
- {
- submesh.HasTangents = true;
- submesh.Tangents.reserve(numVertices);
- DefaultLogger::get()->debug(" - Has tangents");
- }
- if (reader->getAttributeValue("texture_coords"))
- {
- submesh.Uvs.resize(GetAttribute<unsigned int>(reader, "texture_coords"));
- for(size_t i=0, len=submesh.Uvs.size(); i<len; ++i) {
- submesh.Uvs[i].reserve(numVertices);
- }
- DefaultLogger::get()->debug(Formatter::format() << " - Has " << submesh.Uvs.size() << " texture coords");
- }
-
- if (!submesh.HasPositions) {
- throw DeadlyImportError("Vertex buffer does not contain positions!");
- }
-
- const string nnVertex = "vertex";
- const string nnPosition = "position";
- const string nnNormal = "normal";
- const string nnTangent = "tangent";
- const string nnBinormal = "binormal";
- const string nnTexCoord = "texcoord";
- const string nnColorDiffuse = "colour_diffuse";
- const string nnColorSpecular = "colour_specular";
-
- bool warnBinormal = true;
- bool warnColorDiffuse = true;
- bool warnColorSpecular = true;
-
- NextNode(reader);
- string currentNodeName = reader->getNodeName();
-
- /// @todo Make this loop nicer.
- while(currentNodeName == nnVertex ||
- currentNodeName == nnPosition ||
- currentNodeName == nnNormal ||
- currentNodeName == nnTangent ||
- currentNodeName == nnBinormal ||
- currentNodeName == nnTexCoord ||
- currentNodeName == nnColorDiffuse ||
- currentNodeName == nnColorSpecular)
- {
- if (currentNodeName == nnVertex)
- {
- NextNode(reader);
- currentNodeName = reader->getNodeName();
- }
-
- /// @todo Implement nnBinormal, nnColorDiffuse and nnColorSpecular
-
- if (submesh.HasPositions && currentNodeName == nnPosition)
- {
- aiVector3D NewPos;
- NewPos.x = GetAttribute<float>(reader, "x");
- NewPos.y = GetAttribute<float>(reader, "y");
- NewPos.z = GetAttribute<float>(reader, "z");
- submesh.Positions.push_back(NewPos);
- }
- else if (submesh.HasNormals && currentNodeName == nnNormal)
- {
- aiVector3D NewNormal;
- NewNormal.x = GetAttribute<float>(reader, "x");
- NewNormal.y = GetAttribute<float>(reader, "y");
- NewNormal.z = GetAttribute<float>(reader, "z");
- submesh.Normals.push_back(NewNormal);
- }
- else if (submesh.HasTangents && currentNodeName == nnTangent)
- {
- aiVector3D NewTangent;
- NewTangent.x = GetAttribute<float>(reader, "x");
- NewTangent.y = GetAttribute<float>(reader, "y");
- NewTangent.z = GetAttribute<float>(reader, "z");
- submesh.Tangents.push_back(NewTangent);
- }
- else if (submesh.Uvs.size() > 0 && currentNodeName == nnTexCoord)
- {
- for(size_t i=0, len=submesh.Uvs.size(); i<len; ++i)
- {
- if (currentNodeName != nnTexCoord) {
- throw DeadlyImportError("Vertex buffer declared more UVs than can be found in a vertex");
- }
-
- aiVector3D NewUv;
- NewUv.x = GetAttribute<float>(reader, "u");
- NewUv.y = GetAttribute<float>(reader, "v") * (-1)+1; //flip the uv vertikal, blender exports them so! (ahem... @todo ????)
- submesh.Uvs[i].push_back(NewUv);
-
- NextNode(reader);
- currentNodeName = reader->getNodeName();
- }
- // Continue main loop as above already read next node
- continue;
- }
- else
- {
- /// @todo Remove this stuff once implemented. We only want to log warnings once per element.
- bool warn = true;
- if (currentNodeName == nnBinormal)
- {
- if (warnBinormal)
- {
- warnBinormal = false;
- }
- else
- {
- warn = false;
- }
- }
- else if (currentNodeName == nnColorDiffuse)
- {
- if (warnColorDiffuse)
- {
- warnColorDiffuse = false;
- }
- else
- {
- warn = false;
- }
- }
- else if (currentNodeName == nnColorSpecular)
- {
- if (warnColorSpecular)
- {
- warnColorSpecular = false;
- }
- else
- {
- warn = false;
- }
- }
- if (warn) {
- DefaultLogger::get()->warn(string("Vertex buffer attribute read not implemented for element: ") + currentNodeName);
- }
- }
-
- // Advance
- NextNode(reader);
- currentNodeName = reader->getNodeName();
- }
-
- DefaultLogger::get()->debug(Formatter::format() <<
- " - Positions " << submesh.Positions.size() <<
- " Normals " << submesh.Normals.size() <<
- " TexCoords " << submesh.Uvs.size() <<
- " Tangents " << submesh.Tangents.size());
-
- // Sanity checks
- if (submesh.HasNormals && submesh.Normals.size() != numVertices) {
- throw DeadlyImportError(Formatter::format() << "Read only " << submesh.Normals.size() << " normals when should have read " << numVertices);
- }
- if (submesh.HasTangents && submesh.Tangents.size() != numVertices) {
- throw DeadlyImportError(Formatter::format() << "Read only " << submesh.Tangents.size() << " tangents when should have read " << numVertices);
- }
- for(unsigned int i=0; i<submesh.Uvs.size(); ++i)
- {
- if (submesh.Uvs[i].size() != numVertices) {
- throw DeadlyImportError(Formatter::format() << "Read only " << submesh.Uvs[i].size()
- << " uvs for uv index " << i << " when should have read " << numVertices);
- }
- }
-}
-
-void OgreImporter::ReadBoneWeights(SubMesh &submesh, XmlReader *reader)
-{
- submesh.Weights.resize(submesh.Positions.size());
-
- unsigned int numRead = 0;
- const string nnVertexBoneAssignment = "vertexboneassignment";
-
- NextNode(reader);
- while(CurrentNodeNameEquals(reader, nnVertexBoneAssignment))
- {
- numRead++;
-
- BoneWeight weight;
- weight.Id = GetAttribute<int>(reader, "boneindex");
- weight.Value = GetAttribute<float>(reader, "weight");
-
- //calculate the number of bones used (this is the highest id +1 becuase bone ids start at 0)
- /// @todo This can probably be refactored to something else.
- submesh.BonesUsed = max(submesh.BonesUsed, weight.Id+1);
-
- const unsigned int vertexId = GetAttribute<int>(reader, "vertexindex");
- submesh.Weights[vertexId].push_back(weight);
-
- NextNode(reader);
- }
- DefaultLogger::get()->debug(Formatter::format() << " - Bone weights " << numRead);
-}
-
-void OgreImporter::ProcessSubMesh(SubMesh &submesh, SubMesh &sharedGeometry)
-{
- // Make all vertexes unique. Required by Assimp.
- vector<Face> uniqueFaceList(submesh.Faces.size());
- unsigned int uniqueVertexCount = submesh.Faces.size() * 3;
-
- vector<aiVector3D> uniquePositions(uniqueVertexCount);
- vector<aiVector3D> uniqueNormals(uniqueVertexCount);
- vector<aiVector3D> uniqueTangents(uniqueVertexCount);
-
- vector<vector<BoneWeight> > uniqueWeights(uniqueVertexCount);
- vector<vector<aiVector3D> > uniqueUvs(submesh.UseSharedGeometry ? sharedGeometry.Uvs.size() : submesh.Uvs.size());
-
- for(size_t uvi=0; uvi<uniqueUvs.size(); ++uvi) {
- uniqueUvs[uvi].resize(uniqueVertexCount);
- }
-
- /* Support for shared geometry.
- We can use this loop to copy vertex informations from the shared data pool. In order to do so
- we just use a reference to a submodel instead of our submodel itself */
- SubMesh &vertexSource = (submesh.UseSharedGeometry ? sharedGeometry : submesh);
- if (submesh.UseSharedGeometry)
- {
- submesh.HasPositions = sharedGeometry.HasPositions;
- submesh.HasNormals = sharedGeometry.HasNormals;
- submesh.HasTangents = sharedGeometry.HasTangents;
- submesh.BonesUsed = sharedGeometry.BonesUsed;
- }
-
- for (size_t i=0, flen=submesh.Faces.size(); i<flen; ++i)
- {
- const Face &face = submesh.Faces[i];
-
- // We pre calculate the index values here,
- // because we need them in all vertex attributes.
- unsigned int v1 = face.VertexIndices[0];
- unsigned int v2 = face.VertexIndices[1];
- unsigned int v3 = face.VertexIndices[2];
-
- size_t pos = i*3;
-
- uniqueFaceList[i].VertexIndices[0] = pos;
- uniqueFaceList[i].VertexIndices[1] = pos + 1;
- uniqueFaceList[i].VertexIndices[2] = pos + 2;
-
- uniquePositions[pos] = vertexSource.Positions[v1];
- uniquePositions[pos+1] = vertexSource.Positions[v2];
- uniquePositions[pos+2] = vertexSource.Positions[v3];
-
- if (vertexSource.HasNormals)
- {
- uniqueNormals[pos ] = vertexSource.Normals[v1];
- uniqueNormals[pos+1] = vertexSource.Normals[v2];
- uniqueNormals[pos+2] = vertexSource.Normals[v3];
- }
-
- if (vertexSource.HasTangents)
- {
- uniqueTangents[pos] = vertexSource.Tangents[v1];
- uniqueTangents[pos+1] = vertexSource.Tangents[v2];
- uniqueTangents[pos+2] = vertexSource.Tangents[v3];
- }
-
- for(size_t uvi=0; uvi<uniqueUvs.size(); ++uvi)
- {
- const std::vector<aiVector3D> &uv = vertexSource.Uvs[uvi];
- uniqueUvs[uvi][pos] = uv[v1];
- uniqueUvs[uvi][pos+1] = uv[v2];
- uniqueUvs[uvi][pos+2] = uv[v3];
- }
-
- if (!vertexSource.Weights.empty())
- {
- uniqueWeights[pos] = vertexSource.Weights[v1];
- uniqueWeights[pos+1] = vertexSource.Weights[v2];
- uniqueWeights[pos+2] = vertexSource.Weights[v3];
- }
- }
-
- // Now we have the unique data, but want them in the SubMesh, so we swap all the containers.
- // If we don't have one of them, we just swap empty containers, so everything is ok.
- submesh.Faces.swap(uniqueFaceList);
- submesh.Positions.swap(uniquePositions);
- submesh.Normals.swap(uniqueNormals);
- submesh.Tangents.swap(uniqueTangents);
- submesh.Uvs.swap(uniqueUvs);
- submesh.Weights.swap(uniqueWeights);
-
- // Normalize bone weights
- // For example the Blender exporter doesn't care about whether the sum of all bone
- // weights for a single vertex equals 1 or not, so validate here.
- for(size_t vertexId=0, wlen=submesh.Weights.size(); vertexId<wlen; ++vertexId)
- {
- std::vector<BoneWeight> &weights = submesh.Weights[vertexId];
-
- float sum = 0.0f;
- for(size_t boneId=0, blen=weights.size(); boneId<blen; ++boneId) {
- sum += weights[boneId].Value;
- }
-
- //check if the sum is too far away from 1
- if ((sum < (1.0f - 0.05f)) || (sum > (1.0f + 0.05f)))
- {
- for(size_t boneId=0, blen=weights.size(); boneId<blen; ++boneId) {
- weights[boneId].Value /= sum;
- }
- }
- }
-}
-
-aiMesh *OgreImporter::CreateAssimpSubMesh(aiScene */*pScene*/, const SubMesh& submesh, const vector<Bone>& bones) const
-{
- const size_t sizeVector3D = sizeof(aiVector3D);
-
- aiMesh *dest = new aiMesh();
-
- // Material
- dest->mMaterialIndex = submesh.MaterialIndex;
-
- // Positions
- dest->mVertices = new aiVector3D[submesh.Positions.size()];
- dest->mNumVertices = submesh.Positions.size();
- memcpy(dest->mVertices, &submesh.Positions[0], submesh.Positions.size() * sizeVector3D);
-
- // Normals
- if (submesh.HasNormals)
- {
- dest->mNormals = new aiVector3D[submesh.Normals.size()];
- memcpy(dest->mNormals, &submesh.Normals[0], submesh.Normals.size() * sizeVector3D);
- }
-
- // Tangents
- // Until we have support for bitangents, no tangents will be written
- /// @todo Investigate why the above?
- if (submesh.HasTangents)
- {
- DefaultLogger::get()->warn("Tangents found from Ogre mesh but writing to Assimp mesh not yet supported!");
- //dest->mTangents = new aiVector3D[submesh.Tangents.size()];
- //memcpy(dest->mTangents, &submesh.Tangents[0], submesh.Tangents.size() * sizeVector3D);
- }
-
- // UVs
- for (size_t i=0, len=submesh.Uvs.size(); i<len; ++i)
- {
- dest->mNumUVComponents[i] = 2;
- dest->mTextureCoords[i] = new aiVector3D[submesh.Uvs[i].size()];
- memcpy(dest->mTextureCoords[i], &(submesh.Uvs[i][0]), submesh.Uvs[i].size() * sizeVector3D);
- }
-
- // Bone weights. Convert internal vertex-to-bone mapping to bone-to-vertex.
- vector<vector<aiVertexWeight> > assimpWeights(submesh.BonesUsed);
- for(size_t vertexId=0, len=submesh.Weights.size(); vertexId<len; ++vertexId)
- {
- const vector<BoneWeight> &vertexWeights = submesh.Weights[vertexId];
- for (size_t boneId=0, len=vertexWeights.size(); boneId<len; ++boneId)
- {
- const BoneWeight &ogreWeight = vertexWeights[boneId];
- assimpWeights[ogreWeight.Id].push_back(aiVertexWeight(vertexId, ogreWeight.Value));
- }
- }
-
- // Bones.
- vector<aiBone*> assimpBones;
- assimpBones.reserve(submesh.BonesUsed);
-
- for(size_t boneId=0, len=submesh.BonesUsed; boneId<len; ++boneId)
- {
- const vector<aiVertexWeight> &boneWeights = assimpWeights[boneId];
- if (boneWeights.size() == 0) {
- continue;
- }
-
- // @note The bones list is sorted by id's, this was done in LoadSkeleton.
- aiBone *assimpBone = new aiBone();
- assimpBone->mName = bones[boneId].Name;
- assimpBone->mOffsetMatrix = bones[boneId].BoneToWorldSpace;
- assimpBone->mNumWeights = boneWeights.size();
- assimpBone->mWeights = new aiVertexWeight[boneWeights.size()];
- memcpy(assimpBone->mWeights, &boneWeights[0], boneWeights.size() * sizeof(aiVertexWeight));
-
- assimpBones.push_back(assimpBone);
- }
-
- if (!assimpBones.empty())
- {
- dest->mBones = new aiBone*[assimpBones.size()];
- dest->mNumBones = assimpBones.size();
-
- for(size_t i=0, len=assimpBones.size(); i<len; ++i) {
- dest->mBones[i] = assimpBones[i];
- }
- }
-
- // Faces
- dest->mFaces = new aiFace[submesh.Faces.size()];
- dest->mNumFaces = submesh.Faces.size();
-
- for(size_t i=0, len=submesh.Faces.size(); i<len; ++i)
- {
- dest->mFaces[i].mNumIndices = 3;
- dest->mFaces[i].mIndices = new unsigned int[3];
-
- const Face &f = submesh.Faces[i];
- dest->mFaces[i].mIndices[0] = f.VertexIndices[0];
- dest->mFaces[i].mIndices[1] = f.VertexIndices[1];
- dest->mFaces[i].mIndices[2] = f.VertexIndices[2];
- }
-
- return dest;
-}
-
-} // Ogre
-} // Assimp
-
-#endif // ASSIMP_BUILD_NO_OGRE_IMPORTER
diff --git a/src/3rdparty/assimp/code/OgreParsingUtils.h b/src/3rdparty/assimp/code/OgreParsingUtils.h
index ac1e58173..d3a7aa8bf 100644
--- a/src/3rdparty/assimp/code/OgreParsingUtils.h
+++ b/src/3rdparty/assimp/code/OgreParsingUtils.h
@@ -1,3 +1,42 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
#ifndef AI_OGREPARSINGUTILS_H_INC
#define AI_OGREPARSINGUTILS_H_INC
@@ -5,144 +44,13 @@
#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
#include "ParsingUtils.h"
-#include "irrXMLWrapper.h"
-#include "fast_atof.h"
#include <functional>
+
namespace Assimp
{
namespace Ogre
{
-typedef irr::io::IrrXMLReader XmlReader;
-
-static void ThrowAttibuteError(const XmlReader* reader, const std::string &name, const std::string &error = "")
-{
- if (!error.empty())
- {
- throw DeadlyImportError(error + " in node '" + std::string(reader->getNodeName()) + "' and attribute '" + name + "'");
- }
- else
- {
- throw DeadlyImportError("Attribute '" + name + "' does not exist in node '" + std::string(reader->getNodeName()) + "'");
- }
-}
-
-template<typename T>
-inline T GetAttribute(const XmlReader* reader, const std::string &name);
-
-template<>
-inline int GetAttribute<int>(const XmlReader* reader, const std::string &name)
-{
- const char* value = reader->getAttributeValue(name.c_str());
- if (value)
- {
- return atoi(value);
- }
- else
- {
- ThrowAttibuteError(reader, name);
- return 0;
- }
-}
-
-template<>
-inline unsigned int GetAttribute<unsigned int>(const XmlReader* reader, const std::string &name)
-{
- const char* value = reader->getAttributeValue(name.c_str());
- if (value)
- {
- return static_cast<unsigned int>(atoi(value)); ///< @todo Find a better way...
- }
- else
- {
- ThrowAttibuteError(reader, name);
- return 0;
- }
-}
-
-template<>
-inline float GetAttribute<float>(const XmlReader* reader, const std::string &name)
-{
- const char* value = reader->getAttributeValue(name.c_str());
- if (value)
- {
- return fast_atof(value);
- }
- else
- {
- ThrowAttibuteError(reader, name);
- return 0.f;
- }
-}
-
-template<>
-inline std::string GetAttribute<std::string>(const XmlReader* reader, const std::string &name)
-{
- const char* value = reader->getAttributeValue(name.c_str());
- if (value)
- {
- return std::string(value);
- }
- else
- {
- ThrowAttibuteError(reader, name);
- return "";
- }
-}
-
-template<>
-inline bool GetAttribute<bool>(const XmlReader* reader, const std::string &name)
-{
- std::string value = GetAttribute<std::string>(reader, name);
- if (ASSIMP_stricmp(value, "true") == 0)
- {
- return true;
- }
- else if (ASSIMP_stricmp(value, "false") == 0)
- {
- return false;
- }
- else
- {
- ThrowAttibuteError(reader, name, "Boolean value is expected to be 'true' or 'false', encountered '" + value + "'");
- return false;
- }
-}
-
-inline bool NextNode(XmlReader* reader)
-{
- do
- {
- if (!reader->read()) {
- return false;
- }
- }
- while(reader->getNodeType() != irr::io::EXN_ELEMENT);
- return true;
-}
-
-inline bool CurrentNodeNameEquals(const XmlReader* reader, const std::string &name)
-{
- return (ASSIMP_stricmp(std::string(reader->getNodeName()), name) == 0);
-}
-
-/// Skips a line from current @ss position until a newline. Returns the skipped part.
-static inline std::string SkipLine(std::stringstream &ss)
-{
- std::string skipped;
- getline(ss, skipped);
- return skipped;
-}
-
-/// Skips a line and reads next element from @c ss to @c nextElement.
-/** @return Skipped line content until newline. */
-static inline std::string NextAfterNewLine(std::stringstream &ss, std::string &nextElement)
-{
- std::string skipped = SkipLine(ss);
- ss >> nextElement;
- return skipped;
-}
-
/// Returns a lower cased copy of @s.
static inline std::string ToLower(std::string s)
{
@@ -207,6 +115,23 @@ static inline std::string &Trim(std::string &s, bool newlines = true)
return TrimLeft(TrimRight(s, newlines), newlines);
}
+/// Skips a line from current @ss position until a newline. Returns the skipped part.
+static inline std::string SkipLine(std::stringstream &ss)
+{
+ std::string skipped;
+ getline(ss, skipped);
+ return skipped;
+}
+
+/// Skips a line and reads next element from @c ss to @c nextElement.
+/** @return Skipped line content until newline. */
+static inline std::string NextAfterNewLine(std::stringstream &ss, std::string &nextElement)
+{
+ std::string skipped = SkipLine(ss);
+ ss >> nextElement;
+ return skipped;
+}
+
} // Ogre
} // Assimp
diff --git a/src/3rdparty/assimp/code/OgreSkeleton.cpp b/src/3rdparty/assimp/code/OgreSkeleton.cpp
deleted file mode 100644
index cc006dc09..000000000
--- a/src/3rdparty/assimp/code/OgreSkeleton.cpp
+++ /dev/null
@@ -1,446 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2012, assimp team
-All rights reserved.
-
-Redistribution and use of this software in aSource and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of aSource 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.
-
-----------------------------------------------------------------------
-*/
-
-#include "AssimpPCH.h"
-
-#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
-
-#include "OgreImporter.h"
-#include "TinyFormatter.h"
-
-using namespace std;
-
-namespace Assimp
-{
-namespace Ogre
-{
-
-void OgreImporter::ReadSkeleton(const std::string &/*pFile*/, Assimp::IOSystem *pIOHandler, const aiScene */*pScene*/,
- const std::string &skeletonFile, vector<Bone> &Bones, vector<Animation> &Animations) const
-{
- string filename = skeletonFile;
- if (EndsWith(filename, ".skeleton"))
- {
- DefaultLogger::get()->warn("Mesh is referencing a Ogre binary skeleton. Parsing binary Ogre assets is not supported at the moment. Trying to find .skeleton.xml file instead.");
- filename += ".xml";
- }
-
- if (!pIOHandler->Exists(filename))
- {
- DefaultLogger::get()->error("Failed to find skeleton file '" + filename + "', skeleton will be missing.");
- return;
- }
-
- boost::scoped_ptr<IOStream> file(pIOHandler->Open(filename));
- if (!file.get()) {
- throw DeadlyImportError("Failed to open skeleton file " + filename);
- }
-
- boost::scoped_ptr<CIrrXML_IOStreamReader> stream(new CIrrXML_IOStreamReader(file.get()));
- XmlReader* reader = irr::io::createIrrXMLReader(stream.get());
- if (!reader) {
- throw DeadlyImportError("Failed to create XML reader for skeleton file " + filename);
- }
-
- DefaultLogger::get()->debug("Reading skeleton '" + filename + "'");
-
- // Root
- NextNode(reader);
- if (!CurrentNodeNameEquals(reader, "skeleton")) {
- throw DeadlyImportError("Root node is not <skeleton> but <" + string(reader->getNodeName()) + "> in " + filename);
- }
-
- // Bones
- NextNode(reader);
- if (!CurrentNodeNameEquals(reader, "bones")) {
- throw DeadlyImportError("No <bones> node in skeleton " + skeletonFile);
- }
-
- NextNode(reader);
- while(CurrentNodeNameEquals(reader, "bone"))
- {
- /** @todo Fix this mandatory ordering. Some exporters might just write rotation first etc.
- There is no technical reason this has to be so strict. */
-
- Bone bone;
- bone.Id = GetAttribute<int>(reader, "id");
- bone.Name = GetAttribute<string>(reader, "name");
-
- NextNode(reader);
- if (!CurrentNodeNameEquals(reader, "position")) {
- throw DeadlyImportError("Position is not first node in Bone!");
- }
-
- bone.Position.x = GetAttribute<float>(reader, "x");
- bone.Position.y = GetAttribute<float>(reader, "y");
- bone.Position.z = GetAttribute<float>(reader, "z");
-
- NextNode(reader);
- if (!CurrentNodeNameEquals(reader, "rotation")) {
- throw DeadlyImportError("Rotation is not the second node in Bone!");
- }
-
- bone.RotationAngle = GetAttribute<float>(reader, "angle");
-
- NextNode(reader);
- if (!CurrentNodeNameEquals(reader, "axis")) {
- throw DeadlyImportError("No axis specified for bone rotation!");
- }
-
- bone.RotationAxis.x = GetAttribute<float>(reader, "x");
- bone.RotationAxis.y = GetAttribute<float>(reader, "y");
- bone.RotationAxis.z = GetAttribute<float>(reader, "z");
-
- Bones.push_back(bone);
-
- NextNode(reader);
- }
-
- // Order bones by Id
- std::sort(Bones.begin(), Bones.end());
-
- // Validate that bone indexes are not skipped.
- /** @note Left this from original authors code, but not sure if this is strictly necessary
- as per the Ogre skeleton spec. It might be more that other (later) code in this imported does not break. */
- for (size_t i=0, len=Bones.size(); i<len; ++i)
- {
- if (static_cast<int>(Bones[i].Id) != static_cast<int>(i)) {
- throw DeadlyImportError("Bone Ids are not in sequence in " + skeletonFile);
- }
- }
-
- DefaultLogger::get()->debug(Formatter::format() << " - Bones " << Bones.size());
-
- // Bone hierarchy
- if (!CurrentNodeNameEquals(reader, "bonehierarchy")) {
- throw DeadlyImportError("No <bonehierarchy> node found after <bones> in " + skeletonFile);
- }
-
- NextNode(reader);
- while(CurrentNodeNameEquals(reader, "boneparent"))
- {
- string childName = GetAttribute<string>(reader, "bone");
- string parentName = GetAttribute<string>(reader, "parent");
-
- vector<Bone>::iterator iterChild = find(Bones.begin(), Bones.end(), childName);
- vector<Bone>::iterator iterParent = find(Bones.begin(), Bones.end(), parentName);
-
- if (iterChild != Bones.end() && iterParent != Bones.end())
- {
- iterChild->ParentId = iterParent->Id;
- iterParent->Children.push_back(iterChild->Id);
- }
- else
- {
- DefaultLogger::get()->warn("Failed to find bones for parenting: Child " + childName + " Parent " + parentName);
- }
-
- NextNode(reader);
- }
-
- // Calculate bone matrices for root bones. Recursively does their children.
- BOOST_FOREACH(Bone &theBone, Bones)
- {
- if (!theBone.IsParented()) {
- theBone.CalculateBoneToWorldSpaceMatrix(Bones);
- }
- }
-
- aiVector3D zeroVec(0.f, 0.f, 0.f);
-
- // Animations
- if (CurrentNodeNameEquals(reader, "animations"))
- {
- DefaultLogger::get()->debug(" - Animations");
-
- NextNode(reader);
- while(CurrentNodeNameEquals(reader, "animation"))
- {
- Animation animation;
- animation.Name = GetAttribute<string>(reader, "name");
- animation.Length = GetAttribute<float>(reader, "length");
-
- // Tracks
- NextNode(reader);
- if (!CurrentNodeNameEquals(reader, "tracks")) {
- throw DeadlyImportError("No <tracks> node found in animation '" + animation.Name + "' in " + skeletonFile);
- }
-
- NextNode(reader);
- while(CurrentNodeNameEquals(reader, "track"))
- {
- Track track;
- track.BoneName = GetAttribute<string>(reader, "bone");
-
- // Keyframes
- NextNode(reader);
- if (!CurrentNodeNameEquals(reader, "keyframes")) {
- throw DeadlyImportError("No <keyframes> node found in a track in animation '" + animation.Name + "' in " + skeletonFile);
- }
-
- NextNode(reader);
- while(CurrentNodeNameEquals(reader, "keyframe"))
- {
- KeyFrame keyFrame;
- keyFrame.Time = GetAttribute<float>(reader, "time");
-
- NextNode(reader);
- while(CurrentNodeNameEquals(reader, "translate") || CurrentNodeNameEquals(reader, "rotate") || CurrentNodeNameEquals(reader, "scale"))
- {
- if (CurrentNodeNameEquals(reader, "translate"))
- {
- keyFrame.Position.x = GetAttribute<float>(reader, "x");
- keyFrame.Position.y = GetAttribute<float>(reader, "y");
- keyFrame.Position.z = GetAttribute<float>(reader, "z");
- }
- else if (CurrentNodeNameEquals(reader, "rotate"))
- {
- float angle = GetAttribute<float>(reader, "angle");
-
- NextNode(reader);
- if (!CurrentNodeNameEquals(reader, "axis")) {
- throw DeadlyImportError("No axis for keyframe rotation in animation '" + animation.Name + "'");
- }
-
- aiVector3D axis;
- axis.x = GetAttribute<float>(reader, "x");
- axis.y = GetAttribute<float>(reader, "y");
- axis.z = GetAttribute<float>(reader, "z");
-
- if (axis.Equal(zeroVec))
- {
- axis.x = 1.0f;
- if (angle != 0) {
- DefaultLogger::get()->warn("Found invalid a key frame with a zero rotation axis in animation '" + animation.Name + "'");
- }
- }
- keyFrame.Rotation = aiQuaternion(axis, angle);
- }
- else if (CurrentNodeNameEquals(reader, "scale"))
- {
- keyFrame.Scaling.x = GetAttribute<float>(reader, "x");
- keyFrame.Scaling.y = GetAttribute<float>(reader, "y");
- keyFrame.Scaling.z = GetAttribute<float>(reader, "z");
- }
- NextNode(reader);
- }
- track.Keyframes.push_back(keyFrame);
- }
- animation.Tracks.push_back(track);
- }
- Animations.push_back(animation);
-
- DefaultLogger::get()->debug(Formatter::format() << " " << animation.Name << " (" << animation.Length << " sec, " << animation.Tracks.size() << " tracks)");
- }
- }
-}
-
-void OgreImporter::CreateAssimpSkeleton(aiScene *pScene, const std::vector<Bone> &bones, const std::vector<Animation> &animations)
-{
- if (bones.empty()) {
- return;
- }
-
- if (!pScene->mRootNode) {
- throw DeadlyImportError("Creating Assimp skeleton: No root node created!");
- }
- if (pScene->mRootNode->mNumChildren > 0) {
- throw DeadlyImportError("Creating Assimp skeleton: Root node already has children!");
- }
-
- // Bones
- vector<aiNode*> rootBones;
- BOOST_FOREACH(const Bone &bone, bones)
- {
- if (!bone.IsParented()) {
- rootBones.push_back(CreateNodeFromBone(bone.Id, bones, pScene->mRootNode));
- }
- }
-
- if (!rootBones.empty())
- {
- pScene->mRootNode->mChildren = new aiNode*[rootBones.size()];
- pScene->mRootNode->mNumChildren = rootBones.size();
-
- for(size_t i=0, len=rootBones.size(); i<len; ++i) {
- pScene->mRootNode->mChildren[i] = rootBones[i];
- }
- }
-
- // TODO: Auf nicht vorhandene Animationskeys achten!
- // @todo Pay attention to non-existing animation Keys (google translated from above german comment)
-
- // Animations
- if (!animations.empty())
- {
- pScene->mAnimations = new aiAnimation*[animations.size()];
- pScene->mNumAnimations = animations.size();
-
- for(size_t ai=0, alen=animations.size(); ai<alen; ++ai)
- {
- const Animation &aSource = animations[ai];
-
- aiAnimation *animation = new aiAnimation();
- animation->mName = aSource.Name;
- animation->mDuration = aSource.Length;
- animation->mTicksPerSecond = 1.0f;
-
- // Tracks
- animation->mChannels = new aiNodeAnim*[aSource.Tracks.size()];
- animation->mNumChannels = aSource.Tracks.size();
-
- for(size_t ti=0, tlen=aSource.Tracks.size(); ti<tlen; ++ti)
- {
- const Track &tSource = aSource.Tracks[ti];
-
- aiNodeAnim *animationNode = new aiNodeAnim();
- animationNode->mNodeName = tSource.BoneName;
-
- // We need this, to access the bones default pose.
- // Which we need to make keys absolute to the default bone pose.
- vector<Bone>::const_iterator boneIter = find(bones.begin(), bones.end(), tSource.BoneName);
- if (boneIter == bones.end())
- {
- for(size_t createdAnimationIndex=0; createdAnimationIndex<ai; createdAnimationIndex++) {
- delete pScene->mAnimations[createdAnimationIndex];
- }
- delete [] pScene->mAnimations;
- pScene->mAnimations = NULL;
- pScene->mNumAnimations = 0;
-
- DefaultLogger::get()->error("Failed to find bone for name " + tSource.BoneName + " when creating animation " + aSource.Name +
- ". This is a serious error, animations wont be imported.");
- return;
- }
-
- aiMatrix4x4 t0, t1;
- aiMatrix4x4 defaultBonePose = aiMatrix4x4::Translation(boneIter->Position, t1) * aiMatrix4x4::Rotation(boneIter->RotationAngle, boneIter->RotationAxis, t0);
-
- // Keyframes
- unsigned int numKeyframes = tSource.Keyframes.size();
-
- animationNode->mPositionKeys = new aiVectorKey[numKeyframes];
- animationNode->mRotationKeys = new aiQuatKey[numKeyframes];
- animationNode->mScalingKeys = new aiVectorKey[numKeyframes];
- animationNode->mNumPositionKeys = numKeyframes;
- animationNode->mNumRotationKeys = numKeyframes;
- animationNode->mNumScalingKeys = numKeyframes;
-
- //...and fill them
- for(size_t kfi=0; kfi<numKeyframes; ++kfi)
- {
- const KeyFrame &kfSource = tSource.Keyframes[kfi];
-
- // Create a matrix to transform a vector from the bones
- // default pose to the bone bones in this animation key
- aiMatrix4x4 t2, t3;
- aiMatrix4x4 keyBonePose =
- aiMatrix4x4::Translation(kfSource.Position, t3) *
- aiMatrix4x4(kfSource.Rotation.GetMatrix()) *
- aiMatrix4x4::Scaling(kfSource.Scaling, t2);
-
- // Calculate the complete transformation from world space to bone space
- aiMatrix4x4 CompleteTransform = defaultBonePose * keyBonePose;
-
- aiVector3D kfPos; aiQuaternion kfRot; aiVector3D kfScale;
- CompleteTransform.Decompose(kfScale, kfRot, kfPos);
-
- animationNode->mPositionKeys[kfi].mTime = static_cast<double>(kfSource.Time);
- animationNode->mRotationKeys[kfi].mTime = static_cast<double>(kfSource.Time);
- animationNode->mScalingKeys[kfi].mTime = static_cast<double>(kfSource.Time);
-
- animationNode->mPositionKeys[kfi].mValue = kfPos;
- animationNode->mRotationKeys[kfi].mValue = kfRot;
- animationNode->mScalingKeys[kfi].mValue = kfScale;
- }
- animation->mChannels[ti] = animationNode;
- }
- pScene->mAnimations[ai] = animation;
- }
- }
-}
-
-aiNode* OgreImporter::CreateNodeFromBone(int boneId, const std::vector<Bone> &bones, aiNode* parent)
-{
- aiMatrix4x4 t0,t1;
- const Bone &source = bones[boneId];
-
- aiNode* boneNode = new aiNode(source.Name);
- boneNode->mParent = parent;
- boneNode->mTransformation = aiMatrix4x4::Translation(source.Position, t0) * aiMatrix4x4::Rotation(source.RotationAngle, source.RotationAxis, t1);
-
- if (!source.Children.empty())
- {
- boneNode->mChildren = new aiNode*[source.Children.size()];
- boneNode->mNumChildren = source.Children.size();
-
- for(size_t i=0, len=source.Children.size(); i<len; ++i) {
- boneNode->mChildren[i] = CreateNodeFromBone(source.Children[i], bones, boneNode);
- }
- }
-
- return boneNode;
-}
-
-void Bone::CalculateBoneToWorldSpaceMatrix(vector<Bone> &Bones)
-{
- aiMatrix4x4 t0, t1;
- aiMatrix4x4 transform = aiMatrix4x4::Rotation(-RotationAngle, RotationAxis, t1) * aiMatrix4x4::Translation(-Position, t0);
-
- if (!IsParented())
- {
- BoneToWorldSpace = transform;
- }
- else
- {
- BoneToWorldSpace = transform * Bones[ParentId].BoneToWorldSpace;
- }
-
- // Recursively for all children now that the parent matrix has been calculated.
- BOOST_FOREACH(int childId, Children)
- {
- Bones[childId].CalculateBoneToWorldSpaceMatrix(Bones);
- }
-}
-
-} // Ogre
-} // Assimp
-
-#endif // ASSIMP_BUILD_NO_OGRE_IMPORTER
diff --git a/src/3rdparty/assimp/code/OgreStructs.cpp b/src/3rdparty/assimp/code/OgreStructs.cpp
new file mode 100644
index 000000000..3eaf2df01
--- /dev/null
+++ b/src/3rdparty/assimp/code/OgreStructs.cpp
@@ -0,0 +1,1193 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+
+#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
+
+#include "OgreStructs.h"
+#include "TinyFormatter.h"
+
+namespace Assimp
+{
+namespace Ogre
+{
+
+// VertexElement
+
+VertexElement::VertexElement() :
+ index(0),
+ source(0),
+ offset(0),
+ type(VET_FLOAT1),
+ semantic(VES_POSITION)
+{
+}
+
+size_t VertexElement::Size() const
+{
+ return TypeSize(type);
+}
+
+size_t VertexElement::ComponentCount() const
+{
+ return ComponentCount(type);
+}
+
+size_t VertexElement::ComponentCount(Type type)
+{
+ switch(type)
+ {
+ case VET_COLOUR:
+ case VET_COLOUR_ABGR:
+ case VET_COLOUR_ARGB:
+ case VET_FLOAT1:
+ case VET_DOUBLE1:
+ case VET_SHORT1:
+ case VET_USHORT1:
+ case VET_INT1:
+ case VET_UINT1:
+ return 1;
+ case VET_FLOAT2:
+ case VET_DOUBLE2:
+ case VET_SHORT2:
+ case VET_USHORT2:
+ case VET_INT2:
+ case VET_UINT2:
+ return 2;
+ case VET_FLOAT3:
+ case VET_DOUBLE3:
+ case VET_SHORT3:
+ case VET_USHORT3:
+ case VET_INT3:
+ case VET_UINT3:
+ return 3;
+ case VET_FLOAT4:
+ case VET_DOUBLE4:
+ case VET_SHORT4:
+ case VET_USHORT4:
+ case VET_INT4:
+ case VET_UINT4:
+ case VET_UBYTE4:
+ return 4;
+ }
+ return 0;
+}
+
+size_t VertexElement::TypeSize(Type type)
+{
+ switch(type)
+ {
+ case VET_COLOUR:
+ case VET_COLOUR_ABGR:
+ case VET_COLOUR_ARGB:
+ return sizeof(unsigned int);
+ case VET_FLOAT1:
+ return sizeof(float);
+ case VET_FLOAT2:
+ return sizeof(float)*2;
+ case VET_FLOAT3:
+ return sizeof(float)*3;
+ case VET_FLOAT4:
+ return sizeof(float)*4;
+ case VET_DOUBLE1:
+ return sizeof(double);
+ case VET_DOUBLE2:
+ return sizeof(double)*2;
+ case VET_DOUBLE3:
+ return sizeof(double)*3;
+ case VET_DOUBLE4:
+ return sizeof(double)*4;
+ case VET_SHORT1:
+ return sizeof(short);
+ case VET_SHORT2:
+ return sizeof(short)*2;
+ case VET_SHORT3:
+ return sizeof(short)*3;
+ case VET_SHORT4:
+ return sizeof(short)*4;
+ case VET_USHORT1:
+ return sizeof(unsigned short);
+ case VET_USHORT2:
+ return sizeof(unsigned short)*2;
+ case VET_USHORT3:
+ return sizeof(unsigned short)*3;
+ case VET_USHORT4:
+ return sizeof(unsigned short)*4;
+ case VET_INT1:
+ return sizeof(int);
+ case VET_INT2:
+ return sizeof(int)*2;
+ case VET_INT3:
+ return sizeof(int)*3;
+ case VET_INT4:
+ return sizeof(int)*4;
+ case VET_UINT1:
+ return sizeof(unsigned int);
+ case VET_UINT2:
+ return sizeof(unsigned int)*2;
+ case VET_UINT3:
+ return sizeof(unsigned int)*3;
+ case VET_UINT4:
+ return sizeof(unsigned int)*4;
+ case VET_UBYTE4:
+ return sizeof(unsigned char)*4;
+ }
+ return 0;
+}
+
+std::string VertexElement::TypeToString()
+{
+ return TypeToString(type);
+}
+
+std::string VertexElement::TypeToString(Type type)
+{
+ switch(type)
+ {
+ case VET_COLOUR: return "COLOUR";
+ case VET_COLOUR_ABGR: return "COLOUR_ABGR";
+ case VET_COLOUR_ARGB: return "COLOUR_ARGB";
+ case VET_FLOAT1: return "FLOAT1";
+ case VET_FLOAT2: return "FLOAT2";
+ case VET_FLOAT3: return "FLOAT3";
+ case VET_FLOAT4: return "FLOAT4";
+ case VET_DOUBLE1: return "DOUBLE1";
+ case VET_DOUBLE2: return "DOUBLE2";
+ case VET_DOUBLE3: return "DOUBLE3";
+ case VET_DOUBLE4: return "DOUBLE4";
+ case VET_SHORT1: return "SHORT1";
+ case VET_SHORT2: return "SHORT2";
+ case VET_SHORT3: return "SHORT3";
+ case VET_SHORT4: return "SHORT4";
+ case VET_USHORT1: return "USHORT1";
+ case VET_USHORT2: return "USHORT2";
+ case VET_USHORT3: return "USHORT3";
+ case VET_USHORT4: return "USHORT4";
+ case VET_INT1: return "INT1";
+ case VET_INT2: return "INT2";
+ case VET_INT3: return "INT3";
+ case VET_INT4: return "INT4";
+ case VET_UINT1: return "UINT1";
+ case VET_UINT2: return "UINT2";
+ case VET_UINT3: return "UINT3";
+ case VET_UINT4: return "UINT4";
+ case VET_UBYTE4: return "UBYTE4";
+ }
+ return "Uknown_VertexElement::Type";
+}
+
+std::string VertexElement::SemanticToString()
+{
+ return SemanticToString(semantic);
+}
+
+std::string VertexElement::SemanticToString(Semantic semantic)
+{
+ switch(semantic)
+ {
+ case VES_POSITION: return "POSITION";
+ case VES_BLEND_WEIGHTS: return "BLEND_WEIGHTS";
+ case VES_BLEND_INDICES: return "BLEND_INDICES";
+ case VES_NORMAL: return "NORMAL";
+ case VES_DIFFUSE: return "DIFFUSE";
+ case VES_SPECULAR: return "SPECULAR";
+ case VES_TEXTURE_COORDINATES: return "TEXTURE_COORDINATES";
+ case VES_BINORMAL: return "BINORMAL";
+ case VES_TANGENT: return "TANGENT";
+ }
+ return "Uknown_VertexElement::Semantic";
+}
+
+// IVertexData
+
+IVertexData::IVertexData() :
+ count(0)
+{
+}
+
+bool IVertexData::HasBoneAssignments() const
+{
+ return !boneAssignments.empty();
+}
+
+void IVertexData::AddVertexMapping(uint32_t oldIndex, uint32_t newIndex)
+{
+ BoneAssignmentsForVertex(oldIndex, newIndex, boneAssignmentsMap[newIndex]);
+ vertexIndexMapping[oldIndex].push_back(newIndex);
+}
+
+void IVertexData::BoneAssignmentsForVertex(uint32_t currentIndex, uint32_t newIndex, VertexBoneAssignmentList &dest) const
+{
+ for (VertexBoneAssignmentList::const_iterator iter=boneAssignments.begin(), end=boneAssignments.end();
+ iter!=end; ++iter)
+ {
+ if (iter->vertexIndex == currentIndex)
+ {
+ VertexBoneAssignment a = (*iter);
+ a.vertexIndex = newIndex;
+ dest.push_back(a);
+ }
+ }
+}
+
+AssimpVertexBoneWeightList IVertexData::AssimpBoneWeights(size_t vertices)
+{
+ AssimpVertexBoneWeightList weights;
+ for(size_t vi=0; vi<vertices; ++vi)
+ {
+ VertexBoneAssignmentList &vertexWeights = boneAssignmentsMap[vi];
+ for (VertexBoneAssignmentList::const_iterator iter=vertexWeights.begin(), end=vertexWeights.end();
+ iter!=end; ++iter)
+ {
+ std::vector<aiVertexWeight> &boneWeights = weights[iter->boneIndex];
+ boneWeights.push_back(aiVertexWeight(vi, iter->weight));
+ }
+ }
+ return weights;
+}
+
+std::set<uint16_t> IVertexData::ReferencedBonesByWeights() const
+{
+ std::set<uint16_t> referenced;
+ for (VertexBoneAssignmentList::const_iterator iter=boneAssignments.begin(), end=boneAssignments.end();
+ iter!=end; ++iter)
+ {
+ referenced.insert(iter->boneIndex);
+ }
+ return referenced;
+}
+
+// VertexData
+
+VertexData::VertexData()
+{
+}
+
+VertexData::~VertexData()
+{
+ Reset();
+}
+
+void VertexData::Reset()
+{
+ // Releases shared ptr memory streams.
+ vertexBindings.clear();
+ vertexElements.clear();
+}
+
+uint32_t VertexData::VertexSize(uint16_t source) const
+{
+ uint32_t size = 0;
+ for(VertexElementList::const_iterator iter=vertexElements.begin(), end=vertexElements.end(); iter != end; ++iter)
+ {
+ if (iter->source == source)
+ size += iter->Size();
+ }
+ return size;
+}
+
+MemoryStream *VertexData::VertexBuffer(uint16_t source)
+{
+ if (vertexBindings.find(source) != vertexBindings.end())
+ return vertexBindings[source].get();
+ return 0;
+}
+
+VertexElement *VertexData::GetVertexElement(VertexElement::Semantic semantic, uint16_t index)
+{
+ for(VertexElementList::iterator iter=vertexElements.begin(), end=vertexElements.end(); iter != end; ++iter)
+ {
+ VertexElement &element = (*iter);
+ if (element.semantic == semantic && element.index == index)
+ return &element;
+ }
+ return 0;
+}
+
+// VertexDataXml
+
+VertexDataXml::VertexDataXml()
+{
+}
+
+bool VertexDataXml::HasPositions() const
+{
+ return !positions.empty();
+}
+
+bool VertexDataXml::HasNormals() const
+{
+ return !normals.empty();
+}
+
+bool VertexDataXml::HasTangents() const
+{
+ return !tangents.empty();
+}
+
+bool VertexDataXml::HasUvs() const
+{
+ return !uvs.empty();
+}
+
+size_t VertexDataXml::NumUvs() const
+{
+ return uvs.size();
+}
+
+// IndexData
+
+IndexData::IndexData() :
+ count(0),
+ faceCount(0),
+ is32bit(false)
+{
+}
+
+IndexData::~IndexData()
+{
+ Reset();
+}
+
+void IndexData::Reset()
+{
+ // Release shared ptr memory stream.
+ buffer.reset();
+}
+
+size_t IndexData::IndexSize() const
+{
+ return (is32bit ? sizeof(uint32_t) : sizeof(uint16_t));
+}
+
+size_t IndexData::FaceSize() const
+{
+ return IndexSize() * 3;
+}
+
+// Mesh
+
+Mesh::Mesh() :
+ sharedVertexData(0),
+ skeleton(0),
+ hasSkeletalAnimations(false)
+{
+}
+
+Mesh::~Mesh()
+{
+ Reset();
+}
+
+void Mesh::Reset()
+{
+ OGRE_SAFE_DELETE(skeleton)
+ OGRE_SAFE_DELETE(sharedVertexData)
+
+ for(size_t i=0, len=subMeshes.size(); i<len; ++i) {
+ OGRE_SAFE_DELETE(subMeshes[i])
+ }
+ subMeshes.clear();
+ for(size_t i=0, len=animations.size(); i<len; ++i) {
+ OGRE_SAFE_DELETE(animations[i])
+ }
+ animations.clear();
+ for(size_t i=0, len=poses.size(); i<len; ++i) {
+ OGRE_SAFE_DELETE(poses[i])
+ }
+ poses.clear();
+}
+
+size_t Mesh::NumSubMeshes() const
+{
+ return subMeshes.size();
+}
+
+SubMesh *Mesh::GetSubMesh(uint16_t index) const
+{
+ for(size_t i=0; i<subMeshes.size(); ++i)
+ if (subMeshes[i]->index == index)
+ return subMeshes[i];
+ return 0;
+}
+
+void Mesh::ConvertToAssimpScene(aiScene* dest)
+{
+ // Setup
+ dest->mNumMeshes = NumSubMeshes();
+ dest->mMeshes = new aiMesh*[dest->mNumMeshes];
+
+ // Create root node
+ dest->mRootNode = new aiNode();
+ dest->mRootNode->mNumMeshes = dest->mNumMeshes;
+ dest->mRootNode->mMeshes = new unsigned int[dest->mRootNode->mNumMeshes];
+
+ // Export meshes
+ for(size_t i=0; i<dest->mNumMeshes; ++i)
+ {
+ dest->mMeshes[i] = subMeshes[i]->ConvertToAssimpMesh(this);
+ dest->mRootNode->mMeshes[i] = i;
+ }
+
+ // Export skeleton
+ if (skeleton)
+ {
+ // Bones
+ if (!skeleton->bones.empty())
+ {
+ BoneList rootBones = skeleton->RootBones();
+ dest->mRootNode->mNumChildren = rootBones.size();
+ dest->mRootNode->mChildren = new aiNode*[dest->mRootNode->mNumChildren];
+
+ for(size_t i=0, len=rootBones.size(); i<len; ++i)
+ {
+ dest->mRootNode->mChildren[i] = rootBones[i]->ConvertToAssimpNode(skeleton, dest->mRootNode);
+ }
+ }
+
+ // Animations
+ if (!skeleton->animations.empty())
+ {
+ dest->mNumAnimations = skeleton->animations.size();
+ dest->mAnimations = new aiAnimation*[dest->mNumAnimations];
+
+ for(size_t i=0, len=skeleton->animations.size(); i<len; ++i)
+ {
+ dest->mAnimations[i] = skeleton->animations[i]->ConvertToAssimpAnimation();
+ }
+ }
+ }
+}
+
+// ISubMesh
+
+ISubMesh::ISubMesh() :
+ index(0),
+ materialIndex(-1),
+ usesSharedVertexData(false),
+ operationType(OT_POINT_LIST)
+{
+}
+
+// SubMesh
+
+SubMesh::SubMesh() :
+ vertexData(0),
+ indexData(new IndexData())
+{
+}
+
+SubMesh::~SubMesh()
+{
+ Reset();
+}
+
+void SubMesh::Reset()
+{
+ OGRE_SAFE_DELETE(vertexData)
+ OGRE_SAFE_DELETE(indexData)
+}
+
+aiMesh *SubMesh::ConvertToAssimpMesh(Mesh *parent)
+{
+ if (operationType != OT_TRIANGLE_LIST) {
+ throw DeadlyImportError(Formatter::format() << "Only mesh operation type OT_TRIANGLE_LIST is supported. Found " << operationType);
+ }
+
+ aiMesh *dest = new aiMesh();
+ dest->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
+
+ if (!name.empty())
+ dest->mName = name;
+
+ // Material index
+ if (materialIndex != -1)
+ dest->mMaterialIndex = materialIndex;
+
+ // Pick source vertex data from shader geometry or from internal geometry.
+ VertexData *src = (!usesSharedVertexData ? vertexData : parent->sharedVertexData);
+
+ VertexElement *positionsElement = src->GetVertexElement(VertexElement::VES_POSITION);
+ VertexElement *normalsElement = src->GetVertexElement(VertexElement::VES_NORMAL);
+ VertexElement *uv1Element = src->GetVertexElement(VertexElement::VES_TEXTURE_COORDINATES, 0);
+ VertexElement *uv2Element = src->GetVertexElement(VertexElement::VES_TEXTURE_COORDINATES, 1);
+
+ // Sanity checks
+ if (!positionsElement) {
+ throw DeadlyImportError("Failed to import Ogre VertexElement::VES_POSITION. Mesh does not have vertex positions!");
+ } else if (positionsElement->type != VertexElement::VET_FLOAT3) {
+ throw DeadlyImportError("Ogre Mesh position vertex element type != VertexElement::VET_FLOAT3. This is not supported.");
+ } else if (normalsElement && normalsElement->type != VertexElement::VET_FLOAT3) {
+ throw DeadlyImportError("Ogre Mesh normal vertex element type != VertexElement::VET_FLOAT3. This is not supported.");
+ }
+
+ // Faces
+ dest->mNumFaces = indexData->faceCount;
+ dest->mFaces = new aiFace[dest->mNumFaces];
+
+ // Assimp required unique vertices, we need to convert from Ogres shared indexing.
+ size_t uniqueVertexCount = dest->mNumFaces * 3;
+ dest->mNumVertices = uniqueVertexCount;
+ dest->mVertices = new aiVector3D[dest->mNumVertices];
+
+ // Source streams
+ MemoryStream *positions = src->VertexBuffer(positionsElement->source);
+ MemoryStream *normals = (normalsElement ? src->VertexBuffer(normalsElement->source) : 0);
+ MemoryStream *uv1 = (uv1Element ? src->VertexBuffer(uv1Element->source) : 0);
+ MemoryStream *uv2 = (uv2Element ? src->VertexBuffer(uv2Element->source) : 0);
+
+ // Element size
+ const size_t sizePosition = positionsElement->Size();
+ const size_t sizeNormal = (normalsElement ? normalsElement->Size() : 0);
+ const size_t sizeUv1 = (uv1Element ? uv1Element->Size() : 0);
+ const size_t sizeUv2 = (uv2Element ? uv2Element->Size() : 0);
+
+ // Vertex width
+ const size_t vWidthPosition = src->VertexSize(positionsElement->source);
+ const size_t vWidthNormal = (normalsElement ? src->VertexSize(normalsElement->source) : 0);
+ const size_t vWidthUv1 = (uv1Element ? src->VertexSize(uv1Element->source) : 0);
+ const size_t vWidthUv2 = (uv2Element ? src->VertexSize(uv2Element->source) : 0);
+
+ bool boneAssignments = src->HasBoneAssignments();
+
+ // Prepare normals
+ if (normals)
+ dest->mNormals = new aiVector3D[dest->mNumVertices];
+
+ // Prepare UVs, ignoring incompatible UVs.
+ if (uv1)
+ {
+ if (uv1Element->type == VertexElement::VET_FLOAT2 || uv1Element->type == VertexElement::VET_FLOAT3)
+ {
+ dest->mNumUVComponents[0] = uv1Element->ComponentCount();
+ dest->mTextureCoords[0] = new aiVector3D[dest->mNumVertices];
+ }
+ else
+ {
+ DefaultLogger::get()->warn(Formatter::format() << "Ogre imported UV0 type " << uv1Element->TypeToString() << " is not compatible with Assimp. Ignoring UV.");
+ uv1 = 0;
+ }
+ }
+ if (uv2)
+ {
+ if (uv2Element->type == VertexElement::VET_FLOAT2 || uv2Element->type == VertexElement::VET_FLOAT3)
+ {
+ dest->mNumUVComponents[1] = uv2Element->ComponentCount();
+ dest->mTextureCoords[1] = new aiVector3D[dest->mNumVertices];
+ }
+ else
+ {
+ DefaultLogger::get()->warn(Formatter::format() << "Ogre imported UV0 type " << uv2Element->TypeToString() << " is not compatible with Assimp. Ignoring UV.");
+ uv2 = 0;
+ }
+ }
+
+ aiVector3D *uv1Dest = (uv1 ? dest->mTextureCoords[0] : 0);
+ aiVector3D *uv2Dest = (uv2 ? dest->mTextureCoords[1] : 0);
+
+ MemoryStream *faces = indexData->buffer.get();
+ for (size_t fi=0, isize=indexData->IndexSize(), fsize=indexData->FaceSize();
+ fi<dest->mNumFaces; ++fi)
+ {
+ // Source Ogre face
+ aiFace ogreFace;
+ ogreFace.mNumIndices = 3;
+ ogreFace.mIndices = new unsigned int[3];
+
+ faces->Seek(fi * fsize, aiOrigin_SET);
+ if (indexData->is32bit)
+ {
+ faces->Read(&ogreFace.mIndices[0], isize, 3);
+ }
+ else
+ {
+ uint16_t iout = 0;
+ for (size_t ii=0; ii<3; ++ii)
+ {
+ faces->Read(&iout, isize, 1);
+ ogreFace.mIndices[ii] = static_cast<unsigned int>(iout);
+ }
+ }
+
+ // Destination Assimp face
+ aiFace &face = dest->mFaces[fi];
+ face.mNumIndices = 3;
+ face.mIndices = new unsigned int[3];
+
+ const size_t pos = fi * 3;
+ for (size_t v=0; v<3; ++v)
+ {
+ const size_t newIndex = pos + v;
+
+ // Write face index
+ face.mIndices[v] = newIndex;
+
+ // Ogres vertex index to ref into the source buffers.
+ const size_t ogreVertexIndex = ogreFace.mIndices[v];
+ src->AddVertexMapping(ogreVertexIndex, newIndex);
+
+ // Position
+ positions->Seek((vWidthPosition * ogreVertexIndex) + positionsElement->offset, aiOrigin_SET);
+ positions->Read(&dest->mVertices[newIndex], sizePosition, 1);
+
+ // Normal
+ if (normals)
+ {
+ normals->Seek((vWidthNormal * ogreVertexIndex) + normalsElement->offset, aiOrigin_SET);
+ normals->Read(&dest->mNormals[newIndex], sizeNormal, 1);
+ }
+ // UV0
+ if (uv1 && uv1Dest)
+ {
+ uv1->Seek((vWidthUv1 * ogreVertexIndex) + uv1Element->offset, aiOrigin_SET);
+ uv1->Read(&uv1Dest[newIndex], sizeUv1, 1);
+ uv1Dest[newIndex].y = (uv1Dest[newIndex].y * -1) + 1; // Flip UV from Ogre to Assimp form
+ }
+ // UV1
+ if (uv2 && uv2Dest)
+ {
+ uv2->Seek((vWidthUv2 * ogreVertexIndex) + uv2Element->offset, aiOrigin_SET);
+ uv2->Read(&uv2Dest[newIndex], sizeUv2, 1);
+ uv2Dest[newIndex].y = (uv2Dest[newIndex].y * -1) + 1; // Flip UV from Ogre to Assimp form
+ }
+ }
+ }
+
+ // Bones and bone weights
+ if (parent->skeleton && boneAssignments)
+ {
+ AssimpVertexBoneWeightList weights = src->AssimpBoneWeights(dest->mNumVertices);
+ std::set<uint16_t> referencedBones = src->ReferencedBonesByWeights();
+
+ dest->mNumBones = referencedBones.size();
+ dest->mBones = new aiBone*[dest->mNumBones];
+
+ size_t assimpBoneIndex = 0;
+ for(std::set<uint16_t>::const_iterator rbIter=referencedBones.begin(), rbEnd=referencedBones.end(); rbIter != rbEnd; ++rbIter, ++assimpBoneIndex)
+ {
+ Bone *bone = parent->skeleton->BoneById((*rbIter));
+ dest->mBones[assimpBoneIndex] = bone->ConvertToAssimpBone(parent->skeleton, weights[bone->id]);
+ }
+ }
+
+ return dest;
+}
+
+// MeshXml
+
+MeshXml::MeshXml() :
+ sharedVertexData(0),
+ skeleton(0)
+{
+}
+
+MeshXml::~MeshXml()
+{
+ Reset();
+}
+
+void MeshXml::Reset()
+{
+ OGRE_SAFE_DELETE(skeleton)
+ OGRE_SAFE_DELETE(sharedVertexData)
+
+ for(size_t i=0, len=subMeshes.size(); i<len; ++i) {
+ OGRE_SAFE_DELETE(subMeshes[i])
+ }
+ subMeshes.clear();
+}
+
+size_t MeshXml::NumSubMeshes() const
+{
+ return subMeshes.size();
+}
+
+SubMeshXml *MeshXml::GetSubMesh(uint16_t index) const
+{
+ for(size_t i=0; i<subMeshes.size(); ++i)
+ if (subMeshes[i]->index == index)
+ return subMeshes[i];
+ return 0;
+}
+
+void MeshXml::ConvertToAssimpScene(aiScene* dest)
+{
+ // Setup
+ dest->mNumMeshes = NumSubMeshes();
+ dest->mMeshes = new aiMesh*[dest->mNumMeshes];
+
+ // Create root node
+ dest->mRootNode = new aiNode();
+ dest->mRootNode->mNumMeshes = dest->mNumMeshes;
+ dest->mRootNode->mMeshes = new unsigned int[dest->mRootNode->mNumMeshes];
+
+ // Export meshes
+ for(size_t i=0; i<dest->mNumMeshes; ++i)
+ {
+ dest->mMeshes[i] = subMeshes[i]->ConvertToAssimpMesh(this);
+ dest->mRootNode->mMeshes[i] = i;
+ }
+
+ // Export skeleton
+ if (skeleton)
+ {
+ // Bones
+ if (!skeleton->bones.empty())
+ {
+ BoneList rootBones = skeleton->RootBones();
+ dest->mRootNode->mNumChildren = rootBones.size();
+ dest->mRootNode->mChildren = new aiNode*[dest->mRootNode->mNumChildren];
+
+ for(size_t i=0, len=rootBones.size(); i<len; ++i)
+ {
+ dest->mRootNode->mChildren[i] = rootBones[i]->ConvertToAssimpNode(skeleton, dest->mRootNode);
+ }
+ }
+
+ // Animations
+ if (!skeleton->animations.empty())
+ {
+ dest->mNumAnimations = skeleton->animations.size();
+ dest->mAnimations = new aiAnimation*[dest->mNumAnimations];
+
+ for(size_t i=0, len=skeleton->animations.size(); i<len; ++i)
+ {
+ dest->mAnimations[i] = skeleton->animations[i]->ConvertToAssimpAnimation();
+ }
+ }
+ }
+}
+
+// SubMeshXml
+
+SubMeshXml::SubMeshXml() :
+ vertexData(0),
+ indexData(new IndexDataXml())
+{
+}
+
+SubMeshXml::~SubMeshXml()
+{
+ Reset();
+}
+
+void SubMeshXml::Reset()
+{
+ OGRE_SAFE_DELETE(indexData)
+ OGRE_SAFE_DELETE(vertexData)
+}
+
+aiMesh *SubMeshXml::ConvertToAssimpMesh(MeshXml *parent)
+{
+ aiMesh *dest = new aiMesh();
+ dest->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
+
+ if (!name.empty())
+ dest->mName = name;
+
+ // Material index
+ if (materialIndex != -1)
+ dest->mMaterialIndex = materialIndex;
+
+ // Faces
+ dest->mNumFaces = indexData->faceCount;
+ dest->mFaces = new aiFace[dest->mNumFaces];
+
+ // Assimp required unique vertices, we need to convert from Ogres shared indexing.
+ size_t uniqueVertexCount = dest->mNumFaces * 3;
+ dest->mNumVertices = uniqueVertexCount;
+ dest->mVertices = new aiVector3D[dest->mNumVertices];
+
+ VertexDataXml *src = (!usesSharedVertexData ? vertexData : parent->sharedVertexData);
+ bool boneAssignments = src->HasBoneAssignments();
+ bool normals = src->HasNormals();
+ size_t uvs = src->NumUvs();
+
+ // Prepare normals
+ if (normals)
+ dest->mNormals = new aiVector3D[dest->mNumVertices];
+
+ // Prepare UVs
+ for(size_t uvi=0; uvi<uvs; ++uvi)
+ {
+ dest->mNumUVComponents[uvi] = 2;
+ dest->mTextureCoords[uvi] = new aiVector3D[dest->mNumVertices];
+ }
+
+ for (size_t fi=0; fi<dest->mNumFaces; ++fi)
+ {
+ // Source Ogre face
+ aiFace &ogreFace = indexData->faces[fi];
+
+ // Destination Assimp face
+ aiFace &face = dest->mFaces[fi];
+ face.mNumIndices = 3;
+ face.mIndices = new unsigned int[3];
+
+ const size_t pos = fi * 3;
+ for (size_t v=0; v<3; ++v)
+ {
+ const size_t newIndex = pos + v;
+
+ // Write face index
+ face.mIndices[v] = newIndex;
+
+ // Ogres vertex index to ref into the source buffers.
+ const size_t ogreVertexIndex = ogreFace.mIndices[v];
+ src->AddVertexMapping(ogreVertexIndex, newIndex);
+
+ // Position
+ dest->mVertices[newIndex] = src->positions[ogreVertexIndex];
+
+ // Normal
+ if (normals)
+ dest->mNormals[newIndex] = src->normals[ogreVertexIndex];
+
+ // UVs
+ for(size_t uvi=0; uvi<uvs; ++uvi)
+ {
+ aiVector3D *uvDest = dest->mTextureCoords[uvi];
+ std::vector<aiVector3D> &uvSrc = src->uvs[uvi];
+ uvDest[newIndex] = uvSrc[ogreVertexIndex];
+ }
+ }
+ }
+
+ // Bones and bone weights
+ if (parent->skeleton && boneAssignments)
+ {
+ AssimpVertexBoneWeightList weights = src->AssimpBoneWeights(dest->mNumVertices);
+ std::set<uint16_t> referencedBones = src->ReferencedBonesByWeights();
+
+ dest->mNumBones = referencedBones.size();
+ dest->mBones = new aiBone*[dest->mNumBones];
+
+ size_t assimpBoneIndex = 0;
+ for(std::set<uint16_t>::const_iterator rbIter=referencedBones.begin(), rbEnd=referencedBones.end(); rbIter != rbEnd; ++rbIter, ++assimpBoneIndex)
+ {
+ Bone *bone = parent->skeleton->BoneById((*rbIter));
+ dest->mBones[assimpBoneIndex] = bone->ConvertToAssimpBone(parent->skeleton, weights[bone->id]);
+ }
+ }
+
+ return dest;
+}
+
+// Animation
+
+Animation::Animation(Skeleton *parent) :
+ parentSkeleton(parent),
+ parentMesh(0),
+ length(0.0f),
+ baseTime(-1.0f)
+{
+}
+
+Animation::Animation(Mesh *parent) :
+ parentMesh(parent),
+ parentSkeleton(0),
+ length(0.0f),
+ baseTime(-1.0f)
+{
+}
+
+VertexData *Animation::AssociatedVertexData(VertexAnimationTrack *track) const
+{
+ if (!parentMesh)
+ return 0;
+
+ bool sharedGeom = (track->target == 0);
+ if (sharedGeom)
+ return parentMesh->sharedVertexData;
+ else
+ return parentMesh->GetSubMesh(track->target-1)->vertexData;
+}
+
+aiAnimation *Animation::ConvertToAssimpAnimation()
+{
+ aiAnimation *anim = new aiAnimation();
+ anim->mName = name;
+ anim->mDuration = static_cast<double>(length);
+ anim->mTicksPerSecond = 1.0;
+
+ // Tracks
+ if (!tracks.empty())
+ {
+ anim->mNumChannels = tracks.size();
+ anim->mChannels = new aiNodeAnim*[anim->mNumChannels];
+
+ for(size_t i=0, len=tracks.size(); i<len; ++i)
+ {
+ anim->mChannels[i] = tracks[i].ConvertToAssimpAnimationNode(parentSkeleton);
+ }
+ }
+ return anim;
+}
+
+// Skeleton
+
+Skeleton::Skeleton() :
+ blendMode(ANIMBLEND_AVERAGE)
+{
+}
+
+Skeleton::~Skeleton()
+{
+ Reset();
+}
+
+void Skeleton::Reset()
+{
+ for(size_t i=0, len=bones.size(); i<len; ++i) {
+ OGRE_SAFE_DELETE(bones[i])
+ }
+ bones.clear();
+ for(size_t i=0, len=animations.size(); i<len; ++i) {
+ OGRE_SAFE_DELETE(animations[i])
+ }
+ animations.clear();
+}
+
+BoneList Skeleton::RootBones() const
+{
+ BoneList rootBones;
+ for(BoneList::const_iterator iter = bones.begin(); iter != bones.end(); ++iter)
+ {
+ if (!(*iter)->IsParented())
+ rootBones.push_back((*iter));
+ }
+ return rootBones;
+}
+
+size_t Skeleton::NumRootBones() const
+{
+ size_t num = 0;
+ for(BoneList::const_iterator iter = bones.begin(); iter != bones.end(); ++iter)
+ {
+ if (!(*iter)->IsParented())
+ num++;
+ }
+ return num;
+}
+
+Bone *Skeleton::BoneByName(const std::string &name) const
+{
+ for(BoneList::const_iterator iter = bones.begin(); iter != bones.end(); ++iter)
+ {
+ if ((*iter)->name == name)
+ return (*iter);
+ }
+ return 0;
+}
+
+Bone *Skeleton::BoneById(uint16_t id) const
+{
+ for(BoneList::const_iterator iter = bones.begin(); iter != bones.end(); ++iter)
+ {
+ if ((*iter)->id == id)
+ return (*iter);
+ }
+ return 0;
+}
+
+// Bone
+
+Bone::Bone() :
+ id(0),
+ parent(0),
+ parentId(-1),
+ scale(1.0f, 1.0f, 1.0f)
+{
+}
+
+bool Bone::IsParented() const
+{
+ return (parentId != -1 && parent != 0);
+}
+
+uint16_t Bone::ParentId() const
+{
+ return static_cast<uint16_t>(parentId);
+}
+
+void Bone::AddChild(Bone *bone)
+{
+ if (!bone)
+ return;
+ if (bone->IsParented())
+ throw DeadlyImportError("Attaching child Bone that is already parented: " + bone->name);
+
+ bone->parent = this;
+ bone->parentId = id;
+ children.push_back(bone->id);
+}
+
+void Bone::CalculateWorldMatrixAndDefaultPose(Skeleton *skeleton)
+{
+ if (!IsParented())
+ worldMatrix = aiMatrix4x4(scale, rotation, position).Inverse();
+ else
+ worldMatrix = aiMatrix4x4(scale, rotation, position).Inverse() * parent->worldMatrix;
+
+ defaultPose = aiMatrix4x4(scale, rotation, position);
+
+ // Recursively for all children now that the parent matrix has been calculated.
+ for (size_t i=0, len=children.size(); i<len; ++i)
+ {
+ Bone *child = skeleton->BoneById(children[i]);
+ if (!child) {
+ throw DeadlyImportError(Formatter::format() << "CalculateWorldMatrixAndDefaultPose: Failed to find child bone " << children[i] << " for parent " << id << " " << name);
+ }
+ child->CalculateWorldMatrixAndDefaultPose(skeleton);
+ }
+}
+
+aiNode *Bone::ConvertToAssimpNode(Skeleton *skeleton, aiNode *parentNode)
+{
+ // Bone node
+ aiNode* node = new aiNode(name);
+ node->mParent = parentNode;
+ node->mTransformation = defaultPose;
+
+ // Children
+ if (!children.empty())
+ {
+ node->mNumChildren = children.size();
+ node->mChildren = new aiNode*[node->mNumChildren];
+
+ for(size_t i=0, len=children.size(); i<len; ++i)
+ {
+ Bone *child = skeleton->BoneById(children[i]);
+ if (!child) {
+ throw DeadlyImportError(Formatter::format() << "ConvertToAssimpNode: Failed to find child bone " << children[i] << " for parent " << id << " " << name);
+ }
+ node->mChildren[i] = child->ConvertToAssimpNode(skeleton, node);
+ }
+ }
+ return node;
+}
+
+aiBone *Bone::ConvertToAssimpBone(Skeleton *parent, const std::vector<aiVertexWeight> &boneWeights)
+{
+ aiBone *bone = new aiBone();
+ bone->mName = name;
+ bone->mOffsetMatrix = worldMatrix;
+
+ if (!boneWeights.empty())
+ {
+ bone->mNumWeights = boneWeights.size();
+ bone->mWeights = new aiVertexWeight[boneWeights.size()];
+ memcpy(bone->mWeights, &boneWeights[0], boneWeights.size() * sizeof(aiVertexWeight));
+ }
+
+ return bone;
+}
+
+// VertexAnimationTrack
+
+VertexAnimationTrack::VertexAnimationTrack() :
+ target(0),
+ type(VAT_NONE)
+{
+}
+
+aiNodeAnim *VertexAnimationTrack::ConvertToAssimpAnimationNode(Skeleton *skeleton)
+{
+ if (boneName.empty() || type != VAT_TRANSFORM) {
+ throw DeadlyImportError("VertexAnimationTrack::ConvertToAssimpAnimationNode: Cannot convert track that has no target bone name or is not type of VAT_TRANSFORM");
+ }
+
+ aiNodeAnim *nodeAnim = new aiNodeAnim();
+ nodeAnim->mNodeName = boneName;
+
+ Bone *bone = skeleton->BoneByName(boneName);
+ if (!bone) {
+ throw DeadlyImportError("VertexAnimationTrack::ConvertToAssimpAnimationNode: Failed to find bone " + boneName + " from parent Skeleton");
+ }
+
+ // Keyframes
+ size_t numKeyframes = transformKeyFrames.size();
+
+ nodeAnim->mPositionKeys = new aiVectorKey[numKeyframes];
+ nodeAnim->mRotationKeys = new aiQuatKey[numKeyframes];
+ nodeAnim->mScalingKeys = new aiVectorKey[numKeyframes];
+ nodeAnim->mNumPositionKeys = numKeyframes;
+ nodeAnim->mNumRotationKeys = numKeyframes;
+ nodeAnim->mNumScalingKeys = numKeyframes;
+
+ for(size_t kfi=0; kfi<numKeyframes; ++kfi)
+ {
+ TransformKeyFrame &kfSource = transformKeyFrames[kfi];
+
+ // Calculate the complete transformation from world space to bone space
+ aiVector3D pos; aiQuaternion rot; aiVector3D scale;
+
+ aiMatrix4x4 finalTransform = bone->defaultPose * kfSource.Transform();
+ finalTransform.Decompose(scale, rot, pos);
+
+ double t = static_cast<double>(kfSource.timePos);
+ nodeAnim->mPositionKeys[kfi].mTime = t;
+ nodeAnim->mRotationKeys[kfi].mTime = t;
+ nodeAnim->mScalingKeys[kfi].mTime = t;
+
+ nodeAnim->mPositionKeys[kfi].mValue = pos;
+ nodeAnim->mRotationKeys[kfi].mValue = rot;
+ nodeAnim->mScalingKeys[kfi].mValue = scale;
+ }
+
+ return nodeAnim;
+}
+
+// TransformKeyFrame
+
+TransformKeyFrame::TransformKeyFrame() :
+ timePos(0.0f),
+ scale(1.0f, 1.0f, 1.0f)
+{
+}
+
+aiMatrix4x4 TransformKeyFrame::Transform()
+{
+ return aiMatrix4x4(scale, rotation, position);
+}
+
+} // Ogre
+} // Assimp
+
+#endif // ASSIMP_BUILD_NO_OGRE_IMPORTER
diff --git a/src/3rdparty/assimp/code/OgreStructs.h b/src/3rdparty/assimp/code/OgreStructs.h
new file mode 100644
index 000000000..75cadf4b7
--- /dev/null
+++ b/src/3rdparty/assimp/code/OgreStructs.h
@@ -0,0 +1,681 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+
+#ifndef AI_OGRESTRUCTS_H_INC
+#define AI_OGRESTRUCTS_H_INC
+
+#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
+
+#include "AssimpPCH.h"
+#include "MemoryIOWrapper.h"
+
+/** @note Parts of this implementation, for example enums, deserialization constants and logic
+ has been copied directly with minor modifications from the MIT licensed Ogre3D code base.
+ See more from https://bitbucket.org/sinbad/ogre. */
+
+namespace Assimp
+{
+namespace Ogre
+{
+
+// Forward decl
+class Mesh;
+class MeshXml;
+class SubMesh;
+class SubMeshXml;
+class Skeleton;
+
+#define OGRE_SAFE_DELETE(p) delete p; p=0;
+
+// Typedefs
+typedef Assimp::MemoryIOStream MemoryStream;
+typedef boost::shared_ptr<MemoryStream> MemoryStreamPtr;
+typedef std::map<uint16_t, MemoryStreamPtr> VertexBufferBindings;
+
+// Ogre Vertex Element
+class VertexElement
+{
+public:
+ /// Vertex element semantics, used to identify the meaning of vertex buffer contents
+ enum Semantic {
+ /// Position, 3 reals per vertex
+ VES_POSITION = 1,
+ /// Blending weights
+ VES_BLEND_WEIGHTS = 2,
+ /// Blending indices
+ VES_BLEND_INDICES = 3,
+ /// Normal, 3 reals per vertex
+ VES_NORMAL = 4,
+ /// Diffuse colours
+ VES_DIFFUSE = 5,
+ /// Specular colours
+ VES_SPECULAR = 6,
+ /// Texture coordinates
+ VES_TEXTURE_COORDINATES = 7,
+ /// Binormal (Y axis if normal is Z)
+ VES_BINORMAL = 8,
+ /// Tangent (X axis if normal is Z)
+ VES_TANGENT = 9,
+ /// The number of VertexElementSemantic elements (note - the first value VES_POSITION is 1)
+ VES_COUNT = 9
+ };
+
+ /// Vertex element type, used to identify the base types of the vertex contents
+ enum Type
+ {
+ VET_FLOAT1 = 0,
+ VET_FLOAT2 = 1,
+ VET_FLOAT3 = 2,
+ VET_FLOAT4 = 3,
+ /// alias to more specific colour type - use the current rendersystem's colour packing
+ VET_COLOUR = 4,
+ VET_SHORT1 = 5,
+ VET_SHORT2 = 6,
+ VET_SHORT3 = 7,
+ VET_SHORT4 = 8,
+ VET_UBYTE4 = 9,
+ /// D3D style compact colour
+ VET_COLOUR_ARGB = 10,
+ /// GL style compact colour
+ VET_COLOUR_ABGR = 11,
+ VET_DOUBLE1 = 12,
+ VET_DOUBLE2 = 13,
+ VET_DOUBLE3 = 14,
+ VET_DOUBLE4 = 15,
+ VET_USHORT1 = 16,
+ VET_USHORT2 = 17,
+ VET_USHORT3 = 18,
+ VET_USHORT4 = 19,
+ VET_INT1 = 20,
+ VET_INT2 = 21,
+ VET_INT3 = 22,
+ VET_INT4 = 23,
+ VET_UINT1 = 24,
+ VET_UINT2 = 25,
+ VET_UINT3 = 26,
+ VET_UINT4 = 27
+ };
+
+ VertexElement();
+
+ /// Size of the vertex element in bytes.
+ size_t Size() const;
+
+ /// Count of components in this element, eg. VET_FLOAT3 return 3.
+ size_t ComponentCount() const;
+
+ /// Type as string.
+ std::string TypeToString();
+
+ /// Semantic as string.
+ std::string SemanticToString();
+
+ static size_t TypeSize(Type type);
+ static size_t ComponentCount(Type type);
+ static std::string TypeToString(Type type);
+ static std::string SemanticToString(Semantic semantic);
+
+ uint16_t index;
+ uint16_t source;
+ uint16_t offset;
+ Type type;
+ Semantic semantic;
+};
+typedef std::vector<VertexElement> VertexElementList;
+
+/// Ogre Vertex Bone Assignment
+struct VertexBoneAssignment
+{
+ uint32_t vertexIndex;
+ uint16_t boneIndex;
+ float weight;
+};
+typedef std::vector<VertexBoneAssignment> VertexBoneAssignmentList;
+typedef std::map<uint32_t, VertexBoneAssignmentList > VertexBoneAssignmentsMap;
+typedef std::map<uint16_t, std::vector<aiVertexWeight> > AssimpVertexBoneWeightList;
+
+// Ogre Vertex Data interface, inherited by the binary and XML implementations.
+class IVertexData
+{
+public:
+ IVertexData();
+
+ /// Returns if bone assignments are available.
+ bool HasBoneAssignments() const;
+
+ /// Add vertex mapping from old to new index.
+ void AddVertexMapping(uint32_t oldIndex, uint32_t newIndex);
+
+ /// Returns re-mapped bone assignments.
+ /** @note Uses mappings added via AddVertexMapping. */
+ AssimpVertexBoneWeightList AssimpBoneWeights(size_t vertices);
+
+ /// Returns a set of bone indexes that are referenced by bone assignments (weights).
+ std::set<uint16_t> ReferencedBonesByWeights() const;
+
+ /// Vertex count.
+ uint32_t count;
+
+ /// Bone assignments.
+ VertexBoneAssignmentList boneAssignments;
+
+private:
+ void BoneAssignmentsForVertex(uint32_t currentIndex, uint32_t newIndex, VertexBoneAssignmentList &dest) const;
+
+ std::map<uint32_t, std::vector<uint32_t> > vertexIndexMapping;
+ VertexBoneAssignmentsMap boneAssignmentsMap;
+};
+
+// Ogre Vertex Data
+class VertexData : public IVertexData
+{
+public:
+ VertexData();
+ ~VertexData();
+
+ /// Releases all memory that this data structure owns.
+ void Reset();
+
+ /// Get vertex size for @c source.
+ uint32_t VertexSize(uint16_t source) const;
+
+ /// Get vertex buffer for @c source.
+ MemoryStream *VertexBuffer(uint16_t source);
+
+ /// Get vertex element for @c semantic for @c index.
+ VertexElement *GetVertexElement(VertexElement::Semantic semantic, uint16_t index = 0);
+
+ /// Vertex elements.
+ VertexElementList vertexElements;
+
+ /// Vertex buffers mapped to bind index.
+ VertexBufferBindings vertexBindings;
+};
+
+// Ogre Index Data
+class IndexData
+{
+public:
+ IndexData();
+ ~IndexData();
+
+ /// Releases all memory that this data structure owns.
+ void Reset();
+
+ /// Index size in bytes.
+ size_t IndexSize() const;
+
+ /// Face size in bytes.
+ size_t FaceSize() const;
+
+ /// Index count.
+ uint32_t count;
+
+ /// Face count.
+ uint32_t faceCount;
+
+ /// If has 32-bit indexes.
+ bool is32bit;
+
+ /// Index buffer.
+ MemoryStreamPtr buffer;
+};
+
+/// Ogre Pose
+class Pose
+{
+public:
+ struct Vertex
+ {
+ uint32_t index;
+ aiVector3D offset;
+ aiVector3D normal;
+ };
+ typedef std::map<uint32_t, Vertex> PoseVertexMap;
+
+ Pose() : target(0), hasNormals(false) {}
+
+ /// Name.
+ std::string name;
+
+ /// Target.
+ uint16_t target;
+
+ /// Does vertices map have normals.
+ bool hasNormals;
+
+ /// Vertex offset and normals.
+ PoseVertexMap vertices;
+};
+typedef std::vector<Pose*> PoseList;
+
+/// Ogre Pose Key Frame Ref
+struct PoseRef
+{
+ uint16_t index;
+ float influence;
+};
+typedef std::vector<PoseRef> PoseRefList;
+
+/// Ogre Pose Key Frame
+struct PoseKeyFrame
+{
+ /// Time position in the animation.
+ float timePos;
+
+ PoseRefList references;
+};
+typedef std::vector<PoseKeyFrame> PoseKeyFrameList;
+
+/// Ogre Morph Key Frame
+struct MorphKeyFrame
+{
+ /// Time position in the animation.
+ float timePos;
+
+ MemoryStreamPtr buffer;
+};
+typedef std::vector<MorphKeyFrame> MorphKeyFrameList;
+
+/// Ogre animation key frame
+struct TransformKeyFrame
+{
+ TransformKeyFrame();
+
+ aiMatrix4x4 Transform();
+
+ float timePos;
+
+ aiQuaternion rotation;
+ aiVector3D position;
+ aiVector3D scale;
+};
+typedef std::vector<TransformKeyFrame> TransformKeyFrameList;
+
+/// Ogre Animation Track
+struct VertexAnimationTrack
+{
+ enum Type
+ {
+ /// No animation
+ VAT_NONE = 0,
+ /// Morph animation is made up of many interpolated snapshot keyframes
+ VAT_MORPH = 1,
+ /// Pose animation is made up of a single delta pose keyframe
+ VAT_POSE = 2,
+ /// Keyframe that has its on pos, rot and scale for a time position
+ VAT_TRANSFORM = 3
+ };
+
+ VertexAnimationTrack();
+
+ /// Convert to Assimp node animation.
+ aiNodeAnim *ConvertToAssimpAnimationNode(Skeleton *skeleton);
+
+ // Animation type.
+ Type type;
+
+ /// Vertex data target.
+ /** 0 == shared geometry
+ >0 == submesh index + 1 */
+ uint16_t target;
+
+ /// Only valid for VAT_TRANSFORM.
+ std::string boneName;
+
+ /// Only one of these will contain key frames, depending on the type enum.
+ PoseKeyFrameList poseKeyFrames;
+ MorphKeyFrameList morphKeyFrames;
+ TransformKeyFrameList transformKeyFrames;
+};
+typedef std::vector<VertexAnimationTrack> VertexAnimationTrackList;
+
+/// Ogre Animation
+class Animation
+{
+public:
+ Animation(Skeleton *parent);
+ Animation(Mesh *parent);
+
+ /// Returns the associated vertex data for a track in this animation.
+ /** @note Only valid to call when parent Mesh is set. */
+ VertexData *AssociatedVertexData(VertexAnimationTrack *track) const;
+
+ /// Convert to Assimp animation.
+ aiAnimation *ConvertToAssimpAnimation();
+
+ /// Parent mesh.
+ /** @note Set only when animation is read from a mesh. */
+ Mesh *parentMesh;
+
+ /// Parent skeleton.
+ /** @note Set only when animation is read from a skeleton. */
+ Skeleton *parentSkeleton;
+
+ /// Animation name.
+ std::string name;
+
+ /// Base animation name.
+ std::string baseName;
+
+ /// Length in seconds.
+ float length;
+
+ /// Base animation key time.
+ float baseTime;
+
+ /// Animation tracks.
+ VertexAnimationTrackList tracks;
+};
+typedef std::vector<Animation*> AnimationList;
+
+/// Ogre Bone
+class Bone
+{
+public:
+ Bone();
+
+ /// Returns if this bone is parented.
+ bool IsParented() const;
+
+ /// Parent index as uint16_t. Internally int32_t as -1 means unparented.
+ uint16_t ParentId() const;
+
+ /// Add child bone.
+ void AddChild(Bone *bone);
+
+ /// Calculates the world matrix for bone and its children.
+ void CalculateWorldMatrixAndDefaultPose(Skeleton *skeleton);
+
+ /// Convert to Assimp node (animation nodes).
+ aiNode *ConvertToAssimpNode(Skeleton *parent, aiNode *parentNode = 0);
+
+ /// Convert to Assimp bone (mesh bones).
+ aiBone *ConvertToAssimpBone(Skeleton *parent, const std::vector<aiVertexWeight> &boneWeights);
+
+ uint16_t id;
+ std::string name;
+
+ Bone *parent;
+ int32_t parentId;
+ std::vector<uint16_t> children;
+
+ aiVector3D position;
+ aiQuaternion rotation;
+ aiVector3D scale;
+
+ aiMatrix4x4 worldMatrix;
+ aiMatrix4x4 defaultPose;
+};
+typedef std::vector<Bone*> BoneList;
+
+/// Ogre Skeleton
+class Skeleton
+{
+public:
+ enum BlendMode
+ {
+ /// Animations are applied by calculating a weighted average of all animations
+ ANIMBLEND_AVERAGE = 0,
+ /// Animations are applied by calculating a weighted cumulative total
+ ANIMBLEND_CUMULATIVE = 1
+ };
+
+ Skeleton();
+ ~Skeleton();
+
+ /// Releases all memory that this data structure owns.
+ void Reset();
+
+ /// Returns unparented root bones.
+ BoneList RootBones() const;
+
+ /// Returns number of unparented root bones.
+ size_t NumRootBones() const;
+
+ /// Get bone by name.
+ Bone *BoneByName(const std::string &name) const;
+
+ /// Get bone by id.
+ Bone *BoneById(uint16_t id) const;
+
+ BoneList bones;
+ AnimationList animations;
+
+ /// @todo Take blend mode into account, but where?
+ BlendMode blendMode;
+};
+
+/// Ogre Sub Mesh interface, inherited by the binary and XML implementations.
+class ISubMesh
+{
+public:
+ /// @note Full list of Ogre types, not all of them are supported and exposed to Assimp.
+ enum OperationType
+ {
+ /// A list of points, 1 vertex per point
+ OT_POINT_LIST = 1,
+ /// A list of lines, 2 vertices per line
+ OT_LINE_LIST = 2,
+ /// A strip of connected lines, 1 vertex per line plus 1 start vertex
+ OT_LINE_STRIP = 3,
+ /// A list of triangles, 3 vertices per triangle
+ OT_TRIANGLE_LIST = 4,
+ /// A strip of triangles, 3 vertices for the first triangle, and 1 per triangle after that
+ OT_TRIANGLE_STRIP = 5,
+ /// A fan of triangles, 3 vertices for the first triangle, and 1 per triangle after that
+ OT_TRIANGLE_FAN = 6
+ };
+
+ ISubMesh();
+
+ /// SubMesh index.
+ unsigned int index;
+
+ /// SubMesh name.
+ std::string name;
+
+ /// Material used by this submesh.
+ std::string materialRef;
+
+ /// Texture alias information.
+ std::string textureAliasName;
+ std::string textureAliasRef;
+
+ /// Assimp scene material index used by this submesh.
+ /** -1 if no material or material could not be imported. */
+ int materialIndex;
+
+ /// If submesh uses shared geometry from parent mesh.
+ bool usesSharedVertexData;
+
+ /// Operation type.
+ OperationType operationType;
+};
+
+/// Ogre SubMesh
+class SubMesh : public ISubMesh
+{
+public:
+ SubMesh();
+ ~SubMesh();
+
+ /// Releases all memory that this data structure owns.
+ /** @note Vertex and index data contains shared ptrs
+ that are freed automatically. In practice the ref count
+ should be 0 after this reset. */
+ void Reset();
+
+ /// Covert to Assimp mesh.
+ aiMesh *ConvertToAssimpMesh(Mesh *parent);
+
+ /// Vertex data.
+ VertexData *vertexData;
+
+ /// Index data.
+ IndexData *indexData;
+};
+typedef std::vector<SubMesh*> SubMeshList;
+
+/// Ogre Mesh
+class Mesh
+{
+public:
+ Mesh();
+ ~Mesh();
+
+ /// Releases all memory that this data structure owns.
+ void Reset();
+
+ /// Returns number of subMeshes.
+ size_t NumSubMeshes() const;
+
+ /// Returns submesh for @c index.
+ SubMesh *GetSubMesh(uint16_t index) const;
+
+ /// Convert mesh to Assimp scene.
+ void ConvertToAssimpScene(aiScene* dest);
+
+ /// Mesh has skeletal animations.
+ bool hasSkeletalAnimations;
+
+ /// Skeleton reference.
+ std::string skeletonRef;
+
+ /// Skeleton.
+ Skeleton *skeleton;
+
+ /// Vertex data
+ VertexData *sharedVertexData;
+
+ /// Sub meshes.
+ SubMeshList subMeshes;
+
+ /// Animations
+ AnimationList animations;
+
+ /// Poses
+ PoseList poses;
+};
+
+/// Ogre XML Vertex Data
+class VertexDataXml : public IVertexData
+{
+public:
+ VertexDataXml();
+
+ bool HasPositions() const;
+ bool HasNormals() const;
+ bool HasTangents() const;
+ bool HasUvs() const;
+ size_t NumUvs() const;
+
+ std::vector<aiVector3D> positions;
+ std::vector<aiVector3D> normals;
+ std::vector<aiVector3D> tangents;
+ std::vector<std::vector<aiVector3D> > uvs;
+};
+
+/// Ogre XML Index Data
+class IndexDataXml
+{
+public:
+ IndexDataXml() : faceCount(0) {}
+
+ /// Face count.
+ uint32_t faceCount;
+
+ std::vector<aiFace> faces;
+};
+
+/// Ogre XML SubMesh
+class SubMeshXml : public ISubMesh
+{
+public:
+ SubMeshXml();
+ ~SubMeshXml();
+
+ /// Releases all memory that this data structure owns.
+ void Reset();
+
+ aiMesh *ConvertToAssimpMesh(MeshXml *parent);
+
+ IndexDataXml *indexData;
+ VertexDataXml *vertexData;
+};
+typedef std::vector<SubMeshXml*> SubMeshXmlList;
+
+/// Ogre XML Mesh
+class MeshXml
+{
+public:
+ MeshXml();
+ ~MeshXml();
+
+ /// Releases all memory that this data structure owns.
+ void Reset();
+
+ /// Returns number of subMeshes.
+ size_t NumSubMeshes() const;
+
+ /// Returns submesh for @c index.
+ SubMeshXml *GetSubMesh(uint16_t index) const;
+
+ /// Convert mesh to Assimp scene.
+ void ConvertToAssimpScene(aiScene* dest);
+
+ /// Skeleton reference.
+ std::string skeletonRef;
+
+ /// Skeleton.
+ Skeleton *skeleton;
+
+ /// Vertex data
+ VertexDataXml *sharedVertexData;
+
+ /// Sub meshes.
+ SubMeshXmlList subMeshes;
+};
+
+} // Ogre
+} // Assimp
+
+#endif // ASSIMP_BUILD_NO_OGRE_IMPORTER
+#endif // AI_OGRESTRUCTS_H_INC
diff --git a/src/3rdparty/assimp/code/OgreXmlHelper.hpp b/src/3rdparty/assimp/code/OgreXmlHelper.hpp
deleted file mode 100644
index 8a71a4be5..000000000
--- a/src/3rdparty/assimp/code/OgreXmlHelper.hpp
+++ /dev/null
@@ -1,88 +0,0 @@
-
-#include "irrXMLWrapper.h"
-#include "fast_atof.h"
-
-namespace Assimp
-{
-namespace Ogre
-{
-
-typedef irr::io::IrrXMLReader XmlReader;
-
-
-//------------Helper Funktion to Get a Attribute Save---------------
-template<typename t> inline t GetAttribute(XmlReader* Reader, std::string Name);
-
-/*
-{
- BOOST_STATIC_ASSERT(false);
- return t();
-}
-*/
-
-template<> inline int GetAttribute<int>(XmlReader* Reader, std::string Name)
-{
- const char* Value=Reader->getAttributeValue(Name.c_str());
- if(Value)
- return atoi(Value);
- else
- throw DeadlyImportError(std::string("Attribute "+Name+" does not exist in "+Reader->getNodeName()).c_str());
-}
-
-template<> inline unsigned int GetAttribute<unsigned int>(XmlReader* Reader, std::string Name)
-{
- const char* Value=Reader->getAttributeValue(Name.c_str());
- if(Value)
- return static_cast<unsigned int>(atoi(Value));//yes, ugly, but pfff
- else
- throw DeadlyImportError(std::string("Attribute "+Name+" does not exist in "+Reader->getNodeName()).c_str());
-}
-
-template<> inline float GetAttribute<float>(XmlReader* Reader, std::string Name)
-{
- const char* Value=Reader->getAttributeValue(Name.c_str());
- if(Value)
- return fast_atof(Value);
- else
- throw DeadlyImportError(std::string("Attribute "+Name+" does not exist in "+Reader->getNodeName()).c_str());
-}
-
-template<> inline std::string GetAttribute<std::string>(XmlReader* Reader, std::string Name)
-{
- const char* Value=Reader->getAttributeValue(Name.c_str());
- if(Value)
- return std::string(Value);
- else
- throw DeadlyImportError(std::string("Attribute "+Name+" does not exist in "+Reader->getNodeName()).c_str());
-}
-
-template<> inline bool GetAttribute<bool>(XmlReader* Reader, std::string Name)
-{
- const char* Value=Reader->getAttributeValue(Name.c_str());
- if(Value)
- {
- if(Value==std::string("true"))
- return true;
- else if(Value==std::string("false"))
- return false;
- else
- throw DeadlyImportError(std::string("Bool value has invalid value: "+Name+" / "+Value+" / "+Reader->getNodeName()));
- }
- else
- throw DeadlyImportError(std::string("Attribute "+Name+" does not exist in "+Reader->getNodeName()).c_str());
-}
-//__________________________________________________________________
-
-inline bool XmlRead(XmlReader* Reader)
-{
- do
- {
- if(!Reader->read())
- return false;
- }
- while(Reader->getNodeType()!=irr::io::EXN_ELEMENT);
- return true;
-}
-
-}//namespace Ogre
-}//namespace Assimp
diff --git a/src/3rdparty/assimp/code/OgreXmlSerializer.cpp b/src/3rdparty/assimp/code/OgreXmlSerializer.cpp
new file mode 100644
index 000000000..733e36c03
--- /dev/null
+++ b/src/3rdparty/assimp/code/OgreXmlSerializer.cpp
@@ -0,0 +1,1003 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+
+#include "OgreXmlSerializer.h"
+#include "OgreBinarySerializer.h"
+#include "OgreParsingUtils.h"
+
+#include "TinyFormatter.h"
+
+#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
+
+// Define as 1 to get verbose logging.
+#define OGRE_XML_SERIALIZER_DEBUG 0
+
+namespace Assimp
+{
+namespace Ogre
+{
+
+void ThrowAttibuteError(const XmlReader* reader, const std::string &name, const std::string &error = "")
+{
+ if (!error.empty())
+ {
+ throw DeadlyImportError(error + " in node '" + std::string(reader->getNodeName()) + "' and attribute '" + name + "'");
+ }
+ else
+ {
+ throw DeadlyImportError("Attribute '" + name + "' does not exist in node '" + std::string(reader->getNodeName()) + "'");
+ }
+}
+
+template<>
+int32_t OgreXmlSerializer::ReadAttribute<int32_t>(const std::string &name) const
+{
+ if (HasAttribute(name.c_str()))
+ {
+ return static_cast<int32_t>(m_reader->getAttributeValueAsInt(name.c_str()));
+ }
+ else
+ {
+ ThrowAttibuteError(m_reader, name);
+ return 0;
+ }
+}
+
+template<>
+uint32_t OgreXmlSerializer::ReadAttribute<uint32_t>(const std::string &name) const
+{
+ if (HasAttribute(name.c_str()))
+ {
+ /** @note This is hackish. But we are never expecting unsigned values that go outside the
+ int32_t range. Just monitor for negative numbers and kill the import. */
+ int32_t temp = ReadAttribute<int32_t>(name);
+ if (temp >= 0)
+ {
+ return static_cast<uint32_t>(temp);
+ }
+ else
+ {
+ ThrowAttibuteError(m_reader, name, "Found a negative number value where expecting a uint32_t value");
+ }
+ }
+ else
+ {
+ ThrowAttibuteError(m_reader, name);
+ }
+ return 0;
+}
+
+template<>
+uint16_t OgreXmlSerializer::ReadAttribute<uint16_t>(const std::string &name) const
+{
+ if (HasAttribute(name.c_str()))
+ {
+ return static_cast<uint16_t>(ReadAttribute<uint32_t>(name));
+ }
+ else
+ {
+ ThrowAttibuteError(m_reader, name);
+ }
+ return 0;
+}
+
+template<>
+float OgreXmlSerializer::ReadAttribute<float>(const std::string &name) const
+{
+ if (HasAttribute(name.c_str()))
+ {
+ return m_reader->getAttributeValueAsFloat(name.c_str());
+ }
+ else
+ {
+ ThrowAttibuteError(m_reader, name);
+ return 0;
+ }
+}
+
+template<>
+std::string OgreXmlSerializer::ReadAttribute<std::string>(const std::string &name) const
+{
+ const char* value = m_reader->getAttributeValue(name.c_str());
+ if (value)
+ {
+ return std::string(value);
+ }
+ else
+ {
+ ThrowAttibuteError(m_reader, name);
+ return "";
+ }
+}
+
+template<>
+bool OgreXmlSerializer::ReadAttribute<bool>(const std::string &name) const
+{
+ std::string value = Ogre::ToLower(ReadAttribute<std::string>(name));
+ if (ASSIMP_stricmp(value, "true") == 0)
+ {
+ return true;
+ }
+ else if (ASSIMP_stricmp(value, "false") == 0)
+ {
+ return false;
+ }
+ else
+ {
+ ThrowAttibuteError(m_reader, name, "Boolean value is expected to be 'true' or 'false', encountered '" + value + "'");
+ return false;
+ }
+}
+
+bool OgreXmlSerializer::HasAttribute(const std::string &name) const
+{
+ return (m_reader->getAttributeValue(name.c_str()) != 0);
+}
+
+std::string &OgreXmlSerializer::NextNode()
+{
+ do
+ {
+ if (!m_reader->read())
+ {
+ m_currentNodeName = "";
+ return m_currentNodeName;
+ }
+ }
+ while(m_reader->getNodeType() != irr::io::EXN_ELEMENT);
+
+ CurrentNodeName(true);
+#if (OGRE_XML_SERIALIZER_DEBUG == 1)
+ DefaultLogger::get()->debug("<" + m_currentNodeName + ">");
+#endif
+ return m_currentNodeName;
+}
+
+bool OgreXmlSerializer::CurrentNodeNameEquals(const std::string &name) const
+{
+ return (ASSIMP_stricmp(m_currentNodeName, name) == 0);
+}
+
+std::string OgreXmlSerializer::CurrentNodeName(bool forceRead)
+{
+ if (forceRead)
+ m_currentNodeName = std::string(m_reader->getNodeName());
+ return m_currentNodeName;
+}
+
+std::string &OgreXmlSerializer::SkipCurrentNode()
+{
+#if (OGRE_XML_SERIALIZER_DEBUG == 1)
+ DefaultLogger::get()->debug("Skipping node <" + m_currentNodeName + ">");
+#endif
+
+ for(;;)
+ {
+ if (!m_reader->read())
+ {
+ m_currentNodeName = "";
+ return m_currentNodeName;
+ }
+ if (m_reader->getNodeType() != irr::io::EXN_ELEMENT_END)
+ continue;
+ else if (std::string(m_reader->getNodeName()) == m_currentNodeName)
+ break;
+ }
+ return NextNode();
+}
+
+// Mesh XML constants
+
+// <mesh>
+const std::string nnMesh = "mesh";
+const std::string nnSharedGeometry = "sharedgeometry";
+const std::string nnSubMeshes = "submeshes";
+const std::string nnSubMesh = "submesh";
+const std::string nnSubMeshNames = "submeshnames";
+const std::string nnSkeletonLink = "skeletonlink";
+const std::string nnLOD = "levelofdetail";
+const std::string nnExtremes = "extremes";
+const std::string nnPoses = "poses";
+const std::string nnAnimations = "animations";
+
+// <submesh>
+const std::string nnFaces = "faces";
+const std::string nnFace = "face";
+const std::string nnGeometry = "geometry";
+const std::string nnTextures = "textures";
+
+// <mesh/submesh>
+const std::string nnBoneAssignments = "boneassignments";
+
+// <sharedgeometry/geometry>
+const std::string nnVertexBuffer = "vertexbuffer";
+
+// <vertexbuffer>
+const std::string nnVertex = "vertex";
+const std::string nnPosition = "position";
+const std::string nnNormal = "normal";
+const std::string nnTangent = "tangent";
+const std::string nnBinormal = "binormal";
+const std::string nnTexCoord = "texcoord";
+const std::string nnColorDiffuse = "colour_diffuse";
+const std::string nnColorSpecular = "colour_specular";
+
+// <boneassignments>
+const std::string nnVertexBoneAssignment = "vertexboneassignment";
+
+// Skeleton XML constants
+
+// <skeleton>
+const std::string nnSkeleton = "skeleton";
+const std::string nnBones = "bones";
+const std::string nnBoneHierarchy = "bonehierarchy";
+const std::string nnAnimationLinks = "animationlinks";
+
+// <bones>
+const std::string nnBone = "bone";
+const std::string nnRotation = "rotation";
+const std::string nnAxis = "axis";
+const std::string nnScale = "scale";
+
+// <bonehierarchy>
+const std::string nnBoneParent = "boneparent";
+
+// <animations>
+const std::string nnAnimation = "animation";
+const std::string nnTracks = "tracks";
+
+// <tracks>
+const std::string nnTrack = "track";
+const std::string nnKeyFrames = "keyframes";
+const std::string nnKeyFrame = "keyframe";
+const std::string nnTranslate = "translate";
+const std::string nnRotate = "rotate";
+
+// Common XML constants
+
+const std::string anX = "x";
+const std::string anY = "y";
+const std::string anZ = "z";
+
+// Mesh
+
+MeshXml *OgreXmlSerializer::ImportMesh(XmlReader *reader)
+{
+ OgreXmlSerializer serializer(reader);
+
+ MeshXml *mesh = new MeshXml();
+ serializer.ReadMesh(mesh);
+ return mesh;
+}
+
+void OgreXmlSerializer::ReadMesh(MeshXml *mesh)
+{
+ if (NextNode() != nnMesh) {
+ throw DeadlyImportError("Root node is <" + m_currentNodeName + "> expecting <mesh>");
+ }
+
+ DefaultLogger::get()->debug("Reading Mesh");
+
+ NextNode();
+
+ // Root level nodes
+ while(m_currentNodeName == nnSharedGeometry ||
+ m_currentNodeName == nnSubMeshes ||
+ m_currentNodeName == nnSkeletonLink ||
+ m_currentNodeName == nnBoneAssignments ||
+ m_currentNodeName == nnLOD ||
+ m_currentNodeName == nnSubMeshNames ||
+ m_currentNodeName == nnExtremes ||
+ m_currentNodeName == nnPoses ||
+ m_currentNodeName == nnAnimations)
+ {
+ if (m_currentNodeName == nnSharedGeometry)
+ {
+ mesh->sharedVertexData = new VertexDataXml();
+ ReadGeometry(mesh->sharedVertexData);
+ }
+ else if (m_currentNodeName == nnSubMeshes)
+ {
+ NextNode();
+ while(m_currentNodeName == nnSubMesh) {
+ ReadSubMesh(mesh);
+ }
+ }
+ else if (m_currentNodeName == nnBoneAssignments)
+ {
+ ReadBoneAssignments(mesh->sharedVertexData);
+ }
+ else if (m_currentNodeName == nnSkeletonLink)
+ {
+ mesh->skeletonRef = ReadAttribute<std::string>("name");
+ DefaultLogger::get()->debug("Read skeleton link " + mesh->skeletonRef);
+ NextNode();
+ }
+ // Assimp incompatible/ignored nodes
+ else
+ SkipCurrentNode();
+ }
+}
+
+void OgreXmlSerializer::ReadGeometry(VertexDataXml *dest)
+{
+ dest->count = ReadAttribute<uint32_t>("vertexcount");
+ DefaultLogger::get()->debug(Formatter::format() << " - Reading geometry of " << dest->count << " vertices");
+
+ NextNode();
+ while(m_currentNodeName == nnVertexBuffer) {
+ ReadGeometryVertexBuffer(dest);
+ }
+}
+
+void OgreXmlSerializer::ReadGeometryVertexBuffer(VertexDataXml *dest)
+{
+ bool positions = (HasAttribute("positions") && ReadAttribute<bool>("positions"));
+ bool normals = (HasAttribute("normals") && ReadAttribute<bool>("normals"));
+ bool tangents = (HasAttribute("tangents") && ReadAttribute<bool>("tangents"));
+ uint32_t uvs = (HasAttribute("texture_coords") ? ReadAttribute<uint32_t>("texture_coords") : 0);
+
+ // Not having positions is a error only if a previous vertex buffer did not have them.
+ if (!positions && !dest->HasPositions()) {
+ throw DeadlyImportError("Vertex buffer does not contain positions!");
+ }
+
+ if (positions)
+ {
+ DefaultLogger::get()->debug(" - Contains positions");
+ dest->positions.reserve(dest->count);
+ }
+ if (normals)
+ {
+ DefaultLogger::get()->debug(" - Contains normals");
+ dest->normals.reserve(dest->count);
+ }
+ if (tangents)
+ {
+ DefaultLogger::get()->debug(" - Contains tangents");
+ dest->tangents.reserve(dest->count);
+ }
+ if (uvs > 0)
+ {
+ DefaultLogger::get()->debug(Formatter::format() << " - Contains " << uvs << " texture coords");
+ dest->uvs.resize(uvs);
+ for(size_t i=0, len=dest->uvs.size(); i<len; ++i) {
+ dest->uvs[i].reserve(dest->count);
+ }
+ }
+
+ bool warnBinormal = true;
+ bool warnColorDiffuse = true;
+ bool warnColorSpecular = true;
+
+ NextNode();
+
+ while(m_currentNodeName == nnVertex ||
+ m_currentNodeName == nnPosition ||
+ m_currentNodeName == nnNormal ||
+ m_currentNodeName == nnTangent ||
+ m_currentNodeName == nnBinormal ||
+ m_currentNodeName == nnTexCoord ||
+ m_currentNodeName == nnColorDiffuse ||
+ m_currentNodeName == nnColorSpecular)
+ {
+ if (m_currentNodeName == nnVertex) {
+ NextNode();
+ }
+
+ /// @todo Implement nnBinormal, nnColorDiffuse and nnColorSpecular
+
+ if (positions && m_currentNodeName == nnPosition)
+ {
+ aiVector3D pos;
+ pos.x = ReadAttribute<float>(anX);
+ pos.y = ReadAttribute<float>(anY);
+ pos.z = ReadAttribute<float>(anZ);
+ dest->positions.push_back(pos);
+ }
+ else if (normals && m_currentNodeName == nnNormal)
+ {
+ aiVector3D normal;
+ normal.x = ReadAttribute<float>(anX);
+ normal.y = ReadAttribute<float>(anY);
+ normal.z = ReadAttribute<float>(anZ);
+ dest->normals.push_back(normal);
+ }
+ else if (tangents && m_currentNodeName == nnTangent)
+ {
+ aiVector3D tangent;
+ tangent.x = ReadAttribute<float>(anX);
+ tangent.y = ReadAttribute<float>(anY);
+ tangent.z = ReadAttribute<float>(anZ);
+ dest->tangents.push_back(tangent);
+ }
+ else if (uvs > 0 && m_currentNodeName == nnTexCoord)
+ {
+ for(size_t i=0, len=dest->uvs.size(); i<len; ++i)
+ {
+ if (m_currentNodeName != nnTexCoord) {
+ throw DeadlyImportError("Vertex buffer declared more UVs than can be found in a vertex");
+ }
+
+ aiVector3D uv;
+ uv.x = ReadAttribute<float>("u");
+ uv.y = (ReadAttribute<float>("v") * -1) + 1; // Flip UV from Ogre to Assimp form
+ dest->uvs[i].push_back(uv);
+
+ NextNode();
+ }
+ // Continue main loop as above already read next node
+ continue;
+ }
+ else
+ {
+ /// @todo Remove this stuff once implemented. We only want to log warnings once per element.
+ bool warn = true;
+ if (m_currentNodeName == nnBinormal)
+ {
+ if (warnBinormal)
+ {
+ warnBinormal = false;
+ }
+ else
+ {
+ warn = false;
+ }
+ }
+ else if (m_currentNodeName == nnColorDiffuse)
+ {
+ if (warnColorDiffuse)
+ {
+ warnColorDiffuse = false;
+ }
+ else
+ {
+ warn = false;
+ }
+ }
+ else if (m_currentNodeName == nnColorSpecular)
+ {
+ if (warnColorSpecular)
+ {
+ warnColorSpecular = false;
+ }
+ else
+ {
+ warn = false;
+ }
+ }
+ if (warn) {
+ DefaultLogger::get()->warn("Vertex buffer attribute read not implemented for element: " + m_currentNodeName);
+ }
+ }
+
+ // Advance
+ NextNode();
+ }
+
+ // Sanity checks
+ if (dest->positions.size() != dest->count) {
+ throw DeadlyImportError(Formatter::format() << "Read only " << dest->positions.size() << " positions when should have read " << dest->count);
+ }
+ if (normals && dest->normals.size() != dest->count) {
+ throw DeadlyImportError(Formatter::format() << "Read only " << dest->normals.size() << " normals when should have read " << dest->count);
+ }
+ if (tangents && dest->tangents.size() != dest->count) {
+ throw DeadlyImportError(Formatter::format() << "Read only " << dest->tangents.size() << " tangents when should have read " << dest->count);
+ }
+ for(unsigned int i=0; i<dest->uvs.size(); ++i)
+ {
+ if (dest->uvs[i].size() != dest->count) {
+ throw DeadlyImportError(Formatter::format() << "Read only " << dest->uvs[i].size()
+ << " uvs for uv index " << i << " when should have read " << dest->count);
+ }
+ }
+}
+
+void OgreXmlSerializer::ReadSubMesh(MeshXml *mesh)
+{
+ static const std::string anMaterial = "material";
+ static const std::string anUseSharedVertices = "usesharedvertices";
+ static const std::string anCount = "count";
+ static const std::string anV1 = "v1";
+ static const std::string anV2 = "v2";
+ static const std::string anV3 = "v3";
+ static const std::string anV4 = "v4";
+
+ SubMeshXml* submesh = new SubMeshXml();
+
+ if (HasAttribute(anMaterial)) {
+ submesh->materialRef = ReadAttribute<std::string>(anMaterial);
+ }
+ if (HasAttribute(anUseSharedVertices)) {
+ submesh->usesSharedVertexData = ReadAttribute<bool>(anUseSharedVertices);
+ }
+
+ DefaultLogger::get()->debug(Formatter::format() << "Reading SubMesh " << mesh->subMeshes.size());
+ DefaultLogger::get()->debug(Formatter::format() << " - Material: '" << submesh->materialRef << "'");
+ DefaultLogger::get()->debug(Formatter::format() << " - Uses shared geometry: " << (submesh->usesSharedVertexData ? "true" : "false"));
+
+ // TODO: maybe we have always just 1 faces and 1 geometry and always in this order. this loop will only work correct, when the order
+ // of faces and geometry changed, and not if we have more than one of one
+ /// @todo Fix above comment with better read logic below
+
+ bool quadWarned = false;
+
+ NextNode();
+ while(m_currentNodeName == nnFaces ||
+ m_currentNodeName == nnGeometry ||
+ m_currentNodeName == nnTextures ||
+ m_currentNodeName == nnBoneAssignments)
+ {
+ if (m_currentNodeName == nnFaces)
+ {
+ submesh->indexData->faceCount = ReadAttribute<uint32_t>(anCount);
+ submesh->indexData->faces.reserve(submesh->indexData->faceCount);
+
+ NextNode();
+ while(m_currentNodeName == nnFace)
+ {
+ aiFace face;
+ face.mNumIndices = 3;
+ face.mIndices = new unsigned int[3];
+ face.mIndices[0] = ReadAttribute<uint32_t>(anV1);
+ face.mIndices[1] = ReadAttribute<uint32_t>(anV2);
+ face.mIndices[2] = ReadAttribute<uint32_t>(anV3);
+
+ /// @todo Support quads if Ogre even supports them in XML (I'm not sure but I doubt it)
+ if (!quadWarned && HasAttribute(anV4)) {
+ DefaultLogger::get()->warn("Submesh <face> has quads with <v4>, only triangles are supported at the moment!");
+ quadWarned = true;
+ }
+
+ submesh->indexData->faces.push_back(face);
+
+ // Advance
+ NextNode();
+ }
+
+ if (submesh->indexData->faces.size() == submesh->indexData->faceCount)
+ {
+ DefaultLogger::get()->debug(Formatter::format() << " - Faces " << submesh->indexData->faceCount);
+ }
+ else
+ {
+ throw DeadlyImportError(Formatter::format() << "Read only " << submesh->indexData->faces.size() << " faces when should have read " << submesh->indexData->faceCount);
+ }
+ }
+ else if (m_currentNodeName == nnGeometry)
+ {
+ if (submesh->usesSharedVertexData) {
+ throw DeadlyImportError("Found <geometry> in <submesh> when use shared geometry is true. Invalid mesh file.");
+ }
+
+ submesh->vertexData = new VertexDataXml();
+ ReadGeometry(submesh->vertexData);
+ }
+ else if (m_currentNodeName == nnBoneAssignments)
+ {
+ ReadBoneAssignments(submesh->vertexData);
+ }
+ // Assimp incompatible/ignored nodes
+ else
+ SkipCurrentNode();
+ }
+
+ submesh->index = mesh->subMeshes.size();
+ mesh->subMeshes.push_back(submesh);
+}
+
+void OgreXmlSerializer::ReadBoneAssignments(VertexDataXml *dest)
+{
+ if (!dest) {
+ throw DeadlyImportError("Cannot read bone assignments, vertex data is null.");
+ }
+
+ static const std::string anVertexIndex = "vertexindex";
+ static const std::string anBoneIndex = "boneindex";
+ static const std::string anWeight = "weight";
+
+ std::set<uint32_t> influencedVertices;
+
+ NextNode();
+ while(m_currentNodeName == nnVertexBoneAssignment)
+ {
+ VertexBoneAssignment ba;
+ ba.vertexIndex = ReadAttribute<uint32_t>(anVertexIndex);
+ ba.boneIndex = ReadAttribute<uint16_t>(anBoneIndex);
+ ba.weight = ReadAttribute<float>(anWeight);
+
+ dest->boneAssignments.push_back(ba);
+ influencedVertices.insert(ba.vertexIndex);
+
+ NextNode();
+ }
+
+ /** Normalize bone weights.
+ Some exporters wont care if the sum of all bone weights
+ for a single vertex equals 1 or not, so validate here. */
+ const float epsilon = 0.05f;
+ for(std::set<uint32_t>::const_iterator iter=influencedVertices.begin(), end=influencedVertices.end(); iter != end; ++iter)
+ {
+ const uint32_t vertexIndex = (*iter);
+
+ float sum = 0.0f;
+ for (VertexBoneAssignmentList::const_iterator baIter=dest->boneAssignments.begin(), baEnd=dest->boneAssignments.end(); baIter != baEnd; ++baIter)
+ {
+ if (baIter->vertexIndex == vertexIndex)
+ sum += baIter->weight;
+ }
+ if ((sum < (1.0f - epsilon)) || (sum > (1.0f + epsilon)))
+ {
+ for (VertexBoneAssignmentList::iterator baIter=dest->boneAssignments.begin(), baEnd=dest->boneAssignments.end(); baIter != baEnd; ++baIter)
+ {
+ if (baIter->vertexIndex == vertexIndex)
+ baIter->weight /= sum;
+ }
+ }
+ }
+
+ DefaultLogger::get()->debug(Formatter::format() << " - " << dest->boneAssignments.size() << " bone assignments");
+}
+
+// Skeleton
+
+bool OgreXmlSerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, MeshXml *mesh)
+{
+ if (!mesh || mesh->skeletonRef.empty())
+ return false;
+
+ // Highly unusual to see in read world cases but support
+ // XML mesh referencing a binary skeleton file.
+ if (EndsWith(mesh->skeletonRef, ".skeleton", false))
+ {
+ if (OgreBinarySerializer::ImportSkeleton(pIOHandler, mesh))
+ return true;
+
+ /** Last fallback if .skeleton failed to be read. Try reading from
+ .skeleton.xml even if the XML file referenced a binary skeleton.
+ @note This logic was in the previous version and I don't want to break
+ old code that might depends on it. */
+ mesh->skeletonRef = mesh->skeletonRef + ".xml";
+ }
+
+ XmlReaderPtr reader = OpenReader(pIOHandler, mesh->skeletonRef);
+ if (!reader.get())
+ return false;
+
+ Skeleton *skeleton = new Skeleton();
+ OgreXmlSerializer serializer(reader.get());
+ serializer.ReadSkeleton(skeleton);
+ mesh->skeleton = skeleton;
+ return true;
+}
+
+bool OgreXmlSerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, Mesh *mesh)
+{
+ if (!mesh || mesh->skeletonRef.empty())
+ return false;
+
+ XmlReaderPtr reader = OpenReader(pIOHandler, mesh->skeletonRef);
+ if (!reader.get())
+ return false;
+
+ Skeleton *skeleton = new Skeleton();
+ OgreXmlSerializer serializer(reader.get());
+ serializer.ReadSkeleton(skeleton);
+ mesh->skeleton = skeleton;
+ return true;
+}
+
+XmlReaderPtr OgreXmlSerializer::OpenReader(Assimp::IOSystem *pIOHandler, const std::string &filename)
+{
+ if (!EndsWith(filename, ".skeleton.xml", false))
+ {
+ DefaultLogger::get()->error("Imported Mesh is referencing to unsupported '" + filename + "' skeleton file.");
+ return XmlReaderPtr();
+ }
+
+ if (!pIOHandler->Exists(filename))
+ {
+ DefaultLogger::get()->error("Failed to find skeleton file '" + filename + "' that is referenced by imported Mesh.");
+ return XmlReaderPtr();
+ }
+
+ boost::scoped_ptr<IOStream> file(pIOHandler->Open(filename));
+ if (!file.get()) {
+ throw DeadlyImportError("Failed to open skeleton file " + filename);
+ }
+
+ boost::scoped_ptr<CIrrXML_IOStreamReader> stream(new CIrrXML_IOStreamReader(file.get()));
+ XmlReaderPtr reader = XmlReaderPtr(irr::io::createIrrXMLReader(stream.get()));
+ if (!reader.get()) {
+ throw DeadlyImportError("Failed to create XML reader for skeleton file " + filename);
+ }
+ return reader;
+}
+
+void OgreXmlSerializer::ReadSkeleton(Skeleton *skeleton)
+{
+ if (NextNode() != nnSkeleton) {
+ throw DeadlyImportError("Root node is <" + m_currentNodeName + "> expecting <skeleton>");
+ }
+
+ DefaultLogger::get()->debug("Reading Skeleton");
+
+ // Optional blend mode from root node
+ if (HasAttribute("blendmode")) {
+ skeleton->blendMode = (ToLower(ReadAttribute<std::string>("blendmode")) == "cumulative"
+ ? Skeleton::ANIMBLEND_CUMULATIVE : Skeleton::ANIMBLEND_AVERAGE);
+ }
+
+ NextNode();
+
+ // Root level nodes
+ while(m_currentNodeName == nnBones ||
+ m_currentNodeName == nnBoneHierarchy ||
+ m_currentNodeName == nnAnimations ||
+ m_currentNodeName == nnAnimationLinks)
+ {
+ if (m_currentNodeName == nnBones)
+ ReadBones(skeleton);
+ else if (m_currentNodeName == nnBoneHierarchy)
+ ReadBoneHierarchy(skeleton);
+ else if (m_currentNodeName == nnAnimations)
+ ReadAnimations(skeleton);
+ else
+ SkipCurrentNode();
+ }
+}
+
+void OgreXmlSerializer::ReadAnimations(Skeleton *skeleton)
+{
+ if (skeleton->bones.empty()) {
+ throw DeadlyImportError("Cannot read <animations> for a Skeleton without bones");
+ }
+
+ DefaultLogger::get()->debug(" - Animations");
+
+ NextNode();
+ while(m_currentNodeName == nnAnimation)
+ {
+ Animation *anim = new Animation(skeleton);
+ anim->name = ReadAttribute<std::string>("name");
+ anim->length = ReadAttribute<float>("length");
+
+ if (NextNode() != nnTracks) {
+ throw DeadlyImportError(Formatter::format() << "No <tracks> found in <animation> " << anim->name);
+ }
+
+ ReadAnimationTracks(anim);
+ skeleton->animations.push_back(anim);
+
+ DefaultLogger::get()->debug(Formatter::format() << " " << anim->name << " (" << anim->length << " sec, " << anim->tracks.size() << " tracks)");
+ }
+}
+
+void OgreXmlSerializer::ReadAnimationTracks(Animation *dest)
+{
+ NextNode();
+ while(m_currentNodeName == nnTrack)
+ {
+ VertexAnimationTrack track;
+ track.type = VertexAnimationTrack::VAT_TRANSFORM;
+ track.boneName = ReadAttribute<std::string>("bone");
+
+ if (NextNode() != nnKeyFrames) {
+ throw DeadlyImportError(Formatter::format() << "No <keyframes> found in <track> " << dest->name);
+ }
+
+ ReadAnimationKeyFrames(dest, &track);
+
+ dest->tracks.push_back(track);
+ }
+}
+
+void OgreXmlSerializer::ReadAnimationKeyFrames(Animation *anim, VertexAnimationTrack *dest)
+{
+ const aiVector3D zeroVec(0.f, 0.f, 0.f);
+
+ NextNode();
+ while(m_currentNodeName == nnKeyFrame)
+ {
+ TransformKeyFrame keyframe;
+ keyframe.timePos = ReadAttribute<float>("time");
+
+ NextNode();
+ while(m_currentNodeName == nnTranslate || m_currentNodeName == nnRotate || m_currentNodeName == nnScale)
+ {
+ if (m_currentNodeName == nnTranslate)
+ {
+ keyframe.position.x = ReadAttribute<float>(anX);
+ keyframe.position.y = ReadAttribute<float>(anY);
+ keyframe.position.z = ReadAttribute<float>(anZ);
+ }
+ else if (m_currentNodeName == nnRotate)
+ {
+ float angle = ReadAttribute<float>("angle");
+
+ if (NextNode() != nnAxis) {
+ throw DeadlyImportError("No axis specified for keyframe rotation in animation " + anim->name);
+ }
+
+ aiVector3D axis;
+ axis.x = ReadAttribute<float>(anX);
+ axis.y = ReadAttribute<float>(anY);
+ axis.z = ReadAttribute<float>(anZ);
+ if (axis.Equal(zeroVec))
+ {
+ axis.x = 1.0f;
+ if (angle != 0) {
+ DefaultLogger::get()->warn("Found invalid a key frame with a zero rotation axis in animation: " + anim->name);
+ }
+ }
+ keyframe.rotation = aiQuaternion(axis, angle);
+ }
+ else if (m_currentNodeName == nnScale)
+ {
+ keyframe.scale.x = ReadAttribute<float>(anX);
+ keyframe.scale.y = ReadAttribute<float>(anY);
+ keyframe.scale.z = ReadAttribute<float>(anZ);
+ }
+
+ NextNode();
+ }
+
+ dest->transformKeyFrames.push_back(keyframe);
+ }
+}
+
+void OgreXmlSerializer::ReadBoneHierarchy(Skeleton *skeleton)
+{
+ if (skeleton->bones.empty()) {
+ throw DeadlyImportError("Cannot read <bonehierarchy> for a Skeleton without bones");
+ }
+
+ while(NextNode() == nnBoneParent)
+ {
+ const std::string name = ReadAttribute<std::string>("bone");
+ const std::string parentName = ReadAttribute<std::string>("parent");
+
+ Bone *bone = skeleton->BoneByName(name);
+ Bone *parent = skeleton->BoneByName(parentName);
+
+ if (bone && parent)
+ parent->AddChild(bone);
+ else
+ throw DeadlyImportError("Failed to find bones for parenting: Child " + name + " for parent " + parentName);
+ }
+
+ // Calculate bone matrices for root bones. Recursively calculates their children.
+ for (size_t i=0, len=skeleton->bones.size(); i<len; ++i)
+ {
+ Bone *bone = skeleton->bones[i];
+ if (!bone->IsParented())
+ bone->CalculateWorldMatrixAndDefaultPose(skeleton);
+ }
+}
+
+bool BoneCompare(Bone *a, Bone *b)
+{
+ return (a->id < b->id);
+}
+
+void OgreXmlSerializer::ReadBones(Skeleton *skeleton)
+{
+ DefaultLogger::get()->debug(" - Bones");
+
+ NextNode();
+ while(m_currentNodeName == nnBone)
+ {
+ Bone *bone = new Bone();
+ bone->id = ReadAttribute<uint16_t>("id");
+ bone->name = ReadAttribute<std::string>("name");
+
+ NextNode();
+ while(m_currentNodeName == nnPosition ||
+ m_currentNodeName == nnRotation ||
+ m_currentNodeName == nnScale)
+ {
+ if (m_currentNodeName == nnPosition)
+ {
+ bone->position.x = ReadAttribute<float>(anX);
+ bone->position.y = ReadAttribute<float>(anY);
+ bone->position.z = ReadAttribute<float>(anZ);
+ }
+ else if (m_currentNodeName == nnRotation)
+ {
+ float angle = ReadAttribute<float>("angle");
+
+ if (NextNode() != nnAxis) {
+ throw DeadlyImportError(Formatter::format() << "No axis specified for bone rotation in bone " << bone->id);
+ }
+
+ aiVector3D axis;
+ axis.x = ReadAttribute<float>(anX);
+ axis.y = ReadAttribute<float>(anY);
+ axis.z = ReadAttribute<float>(anZ);
+
+ bone->rotation = aiQuaternion(axis, angle);
+ }
+ else if (m_currentNodeName == nnScale)
+ {
+ /// @todo Implement taking scale into account in matrix/pose calculations!
+ if (HasAttribute("factor"))
+ {
+ float factor = ReadAttribute<float>("factor");
+ bone->scale.Set(factor, factor, factor);
+ }
+ else
+ {
+ if (HasAttribute(anX))
+ bone->scale.x = ReadAttribute<float>(anX);
+ if (HasAttribute(anY))
+ bone->scale.y = ReadAttribute<float>(anY);
+ if (HasAttribute(anZ))
+ bone->scale.z = ReadAttribute<float>(anZ);
+ }
+ }
+
+ NextNode();
+ }
+
+ skeleton->bones.push_back(bone);
+ }
+
+ // Order bones by Id
+ std::sort(skeleton->bones.begin(), skeleton->bones.end(), BoneCompare);
+
+ // Validate that bone indexes are not skipped.
+ /** @note Left this from original authors code, but not sure if this is strictly necessary
+ as per the Ogre skeleton spec. It might be more that other (later) code in this imported does not break. */
+ for (size_t i=0, len=skeleton->bones.size(); i<len; ++i)
+ {
+ Bone *b = skeleton->bones[i];
+ DefaultLogger::get()->debug(Formatter::format() << " " << b->id << " " << b->name);
+
+ if (b->id != static_cast<uint16_t>(i)) {
+ throw DeadlyImportError(Formatter::format() << "Bone ids are not in sequence starting from 0. Missing index " << i);
+ }
+ }
+}
+
+} // Ogre
+} // Assimp
+
+#endif // ASSIMP_BUILD_NO_OGRE_IMPORTER
diff --git a/src/3rdparty/assimp/code/OgreXmlSerializer.h b/src/3rdparty/assimp/code/OgreXmlSerializer.h
new file mode 100644
index 000000000..62257f81c
--- /dev/null
+++ b/src/3rdparty/assimp/code/OgreXmlSerializer.h
@@ -0,0 +1,116 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+
+#ifndef AI_OGREXMLSERIALIZER_H_INC
+#define AI_OGREXMLSERIALIZER_H_INC
+
+#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
+
+#include "OgreStructs.h"
+#include "irrXMLWrapper.h"
+
+namespace Assimp
+{
+namespace Ogre
+{
+
+typedef irr::io::IrrXMLReader XmlReader;
+typedef boost::shared_ptr<XmlReader> XmlReaderPtr;
+
+class OgreXmlSerializer
+{
+public:
+ /// Imports mesh and returns the result.
+ /** @note Fatal unrecoverable errors will throw a DeadlyImportError. */
+ static MeshXml *ImportMesh(XmlReader *reader);
+
+ /// Imports skeleton to @c mesh.
+ /** If mesh does not have a skeleton reference or the skeleton file
+ cannot be found it is not a fatal DeadlyImportError.
+ @return If skeleton import was successful. */
+ static bool ImportSkeleton(Assimp::IOSystem *pIOHandler, MeshXml *mesh);
+ static bool ImportSkeleton(Assimp::IOSystem *pIOHandler, Mesh *mesh);
+
+private:
+ OgreXmlSerializer(XmlReader *reader) :
+ m_reader(reader)
+ {
+ }
+
+ static XmlReaderPtr OpenReader(Assimp::IOSystem *pIOHandler, const std::string &filename);
+
+ // Mesh
+ void ReadMesh(MeshXml *mesh);
+ void ReadSubMesh(MeshXml *mesh);
+
+ void ReadGeometry(VertexDataXml *dest);
+ void ReadGeometryVertexBuffer(VertexDataXml *dest);
+
+ void ReadBoneAssignments(VertexDataXml *dest);
+
+ // Skeleton
+ void ReadSkeleton(Skeleton *skeleton);
+
+ void ReadBones(Skeleton *skeleton);
+ void ReadBoneHierarchy(Skeleton *skeleton);
+
+ void ReadAnimations(Skeleton *skeleton);
+ void ReadAnimationTracks(Animation *dest);
+ void ReadAnimationKeyFrames(Animation *anim, VertexAnimationTrack *dest);
+
+ template<typename T>
+ T ReadAttribute(const std::string &name) const;
+ bool HasAttribute(const std::string &name) const;
+
+ std::string &NextNode();
+ std::string &SkipCurrentNode();
+
+ bool CurrentNodeNameEquals(const std::string &name) const;
+ std::string CurrentNodeName(bool forceRead = false);
+
+ XmlReader *m_reader;
+ std::string m_currentNodeName;
+};
+
+} // Ogre
+} // Assimp
+
+#endif // ASSIMP_BUILD_NO_OGRE_IMPORTER
+#endif // AI_OGREXMLSERIALIZER_H_INC
diff --git a/src/3rdparty/assimp/code/Q3BSPFileImporter.cpp b/src/3rdparty/assimp/code/Q3BSPFileImporter.cpp
index ac36e9f53..81a770261 100644
--- a/src/3rdparty/assimp/code/Q3BSPFileImporter.cpp
+++ b/src/3rdparty/assimp/code/Q3BSPFileImporter.cpp
@@ -73,11 +73,11 @@ static const aiImporterDesc desc = {
namespace Assimp {
-//static void getSupportedExtensions(std::vector<std::string> &supportedExtensions) {
-// supportedExtensions.push_back( ".jpg" );
-// supportedExtensions.push_back( ".png" );
-// supportedExtensions.push_back( ".tga" );
-//}
+static void getSupportedExtensions(std::vector<std::string> &supportedExtensions) {
+ supportedExtensions.push_back( ".jpg" );
+ supportedExtensions.push_back( ".png" );
+ supportedExtensions.push_back( ".tga" );
+}
using namespace Q3BSP;
diff --git a/src/3rdparty/assimp/code/Q3BSPZipArchive.cpp b/src/3rdparty/assimp/code/Q3BSPZipArchive.cpp
index d53e474db..ec98a2877 100644
--- a/src/3rdparty/assimp/code/Q3BSPZipArchive.cpp
+++ b/src/3rdparty/assimp/code/Q3BSPZipArchive.cpp
@@ -68,25 +68,25 @@ voidpf IOSystem2Unzip::open(voidpf opaque, const char* filename, int mode) {
return (voidpf) io_system->Open(filename, mode_fopen);
}
-uLong IOSystem2Unzip::read(voidpf /*opaque*/, voidpf stream, void* buf, uLong size) {
+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) {
+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) {
+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) {
+long IOSystem2Unzip::seek(voidpf opaque, voidpf stream, uLong offset, int origin) {
IOStream* io_stream = (IOStream*) stream;
aiOrigin assimp_origin;
@@ -115,7 +115,7 @@ int IOSystem2Unzip::close(voidpf opaque, voidpf stream) {
return 0;
}
-int IOSystem2Unzip::testerror(voidpf /*opaque*/, voidpf /*stream*/) {
+int IOSystem2Unzip::testerror(voidpf opaque, voidpf stream) {
return 0;
}
diff --git a/src/3rdparty/assimp/contrib/clipper/clipper.cpp b/src/3rdparty/assimp/contrib/clipper/clipper.cpp
index f3c323f9b..2b209da69 100644
--- a/src/3rdparty/assimp/contrib/clipper/clipper.cpp
+++ b/src/3rdparty/assimp/contrib/clipper/clipper.cpp
@@ -2124,16 +2124,12 @@ void Clipper::AddOutPt(TEdge *e, const IntPoint &pt)
{
//check for 'rounding' artefacts ...
if (outRec->sides == esNeither && pt.Y == op->pt.Y)
- {
if (ToFront)
{
if (pt.X == op->pt.X +1) return; //ie wrong side of bottomPt
}
- else
- {
- if (pt.X == op->pt.X -1) return; //ie wrong side of bottomPt
- }
- }
+ else if (pt.X == op->pt.X -1) return; //ie wrong side of bottomPt
+
outRec->sides = (EdgeSide)(outRec->sides | e->side);
if (outRec->sides == esBoth)
{
diff --git a/src/3rdparty/assimp/contrib/unzip/crypt.h b/src/3rdparty/assimp/contrib/unzip/crypt.h
index 9d7957765..622f4bc2e 100644
--- a/src/3rdparty/assimp/contrib/unzip/crypt.h
+++ b/src/3rdparty/assimp/contrib/unzip/crypt.h
@@ -34,10 +34,10 @@
*/
static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab)
{
- (void)pcrc_32_tab; // Unused
unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an
* unpredictable manner on 16-bit systems; not a problem
* with any known compiler so far, though */
+
temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2;
return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
}
@@ -47,7 +47,6 @@ static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab)
*/
static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c)
{
- (void)pcrc_32_tab; // Unused
(*(pkeys+0)) = CRC32((*(pkeys+0)), c);
(*(pkeys+1)) += (*(pkeys+0)) & 0xff;
(*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1;
diff --git a/src/3rdparty/assimp/contrib/unzip/ioapi.c b/src/3rdparty/assimp/contrib/unzip/ioapi.c
index af4739443..b7200df75 100644
--- a/src/3rdparty/assimp/contrib/unzip/ioapi.c
+++ b/src/3rdparty/assimp/contrib/unzip/ioapi.c
@@ -69,9 +69,11 @@ int ZCALLBACK ferror_file_func (
voidpf stream);
-voidpf ZCALLBACK fopen_file_func(voidpf opaque, const char* filename, int mode)
+voidpf ZCALLBACK fopen_file_func (opaque, filename, mode)
+ voidpf opaque;
+ const char* filename;
+ int mode;
{
- (void)opaque; // Unused
FILE* file = NULL;
const char* mode_fopen = NULL;
if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
@@ -89,34 +91,44 @@ voidpf ZCALLBACK fopen_file_func(voidpf opaque, const char* filename, int mode)
}
-uLong ZCALLBACK fread_file_func(voidpf opaque, voidpf stream, void* buf, uLong size)
+uLong ZCALLBACK fread_file_func (opaque, stream, buf, size)
+ voidpf opaque;
+ voidpf stream;
+ void* buf;
+ uLong size;
{
- (void)opaque; // Unused
uLong ret;
ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream);
return ret;
}
-uLong ZCALLBACK fwrite_file_func(voidpf opaque, voidpf stream, const void* buf, uLong size)
+uLong ZCALLBACK fwrite_file_func (opaque, stream, buf, size)
+ voidpf opaque;
+ voidpf stream;
+ const void* buf;
+ uLong size;
{
- (void)opaque; // Unused
uLong ret;
ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream);
return ret;
}
-long ZCALLBACK ftell_file_func(voidpf opaque, voidpf stream)
+long ZCALLBACK ftell_file_func (opaque, stream)
+ voidpf opaque;
+ voidpf stream;
{
- (void)opaque; // Unused
long ret;
ret = ftell((FILE *)stream);
return ret;
}
-long ZCALLBACK fseek_file_func(voidpf opaque, voidpf stream, uLong offset, int origin)
+long ZCALLBACK fseek_file_func (opaque, stream, offset, origin)
+ voidpf opaque;
+ voidpf stream;
+ uLong offset;
+ int origin;
{
- (void)opaque; // Unused
int fseek_origin=0;
long ret;
switch (origin)
@@ -137,23 +149,26 @@ long ZCALLBACK fseek_file_func(voidpf opaque, voidpf stream, uLong offset, int o
return ret;
}
-int ZCALLBACK fclose_file_func(voidpf opaque, voidpf stream)
+int ZCALLBACK fclose_file_func (opaque, stream)
+ voidpf opaque;
+ voidpf stream;
{
- (void)opaque; // Unused
int ret;
ret = fclose((FILE *)stream);
return ret;
}
-int ZCALLBACK ferror_file_func(voidpf opaque, voidpf stream)
+int ZCALLBACK ferror_file_func (opaque, stream)
+ voidpf opaque;
+ voidpf stream;
{
- (void)opaque; // Unused
int ret;
ret = ferror((FILE *)stream);
return ret;
}
-void fill_fopen_filefunc(zlib_filefunc_def* pzlib_filefunc_def)
+void fill_fopen_filefunc (pzlib_filefunc_def)
+ zlib_filefunc_def* pzlib_filefunc_def;
{
pzlib_filefunc_def->zopen_file = fopen_file_func;
pzlib_filefunc_def->zread_file = fread_file_func;
diff --git a/src/3rdparty/assimp/contrib/unzip/unzip.h b/src/3rdparty/assimp/contrib/unzip/unzip.h
index 600dfaa41..e3b7f24ee 100644
--- a/src/3rdparty/assimp/contrib/unzip/unzip.h
+++ b/src/3rdparty/assimp/contrib/unzip/unzip.h
@@ -45,6 +45,9 @@
#ifndef _unz_H
#define _unz_H
+#ifdef __cplusplus
+extern "C" {
+#endif
#ifndef _ZLIB_H
# ifdef ASSIMP_BUILD_NO_OWN_ZLIB
@@ -54,17 +57,6 @@
# endif
#endif
-// This needs to be moved down a bit otherwise
-// when using the Zlib headers bundled with Qt
-// an extern C block is redefined within another
-// extern C block resulting in an extern C dangling
-// around causing hundred of template with C linkage e
-// errors
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#ifndef _ZLIBIOAPI_H
#include "ioapi.h"
#endif
diff --git a/src/3rdparty/assimp/code/pstdint.h b/src/3rdparty/assimp/include/assimp/Compiler/pstdint.h
index 5bc322fab..5bc322fab 100644
--- a/src/3rdparty/assimp/code/pstdint.h
+++ b/src/3rdparty/assimp/include/assimp/Compiler/pstdint.h
diff --git a/src/3rdparty/assimp/include/assimp/matrix4x4.h b/src/3rdparty/assimp/include/assimp/matrix4x4.h
index 3d0857fe6..6ed550b7b 100644
--- a/src/3rdparty/assimp/include/assimp/matrix4x4.h
+++ b/src/3rdparty/assimp/include/assimp/matrix4x4.h
@@ -84,8 +84,8 @@ public:
* @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);
+ aiMatrix4x4t(const aiVector3t<TReal>& scaling, const aiQuaterniont<TReal>& rotation,
+ const aiVector3t<TReal>& position);
public:
diff --git a/src/3rdparty/assimp/include/assimp/matrix4x4.inl b/src/3rdparty/assimp/include/assimp/matrix4x4.inl
index 4697d77b6..4fb86b11b 100644
--- a/src/3rdparty/assimp/include/assimp/matrix4x4.inl
+++ b/src/3rdparty/assimp/include/assimp/matrix4x4.inl
@@ -109,7 +109,7 @@ inline aiMatrix4x4t<TReal>::aiMatrix4x4t (const aiMatrix3x3t<TReal>& m)
// ----------------------------------------------------------------------------------------
template <typename TReal>
-inline aiMatrix4x4t<TReal>::aiMatrix4x4t (aiVector3t<TReal>& scaling, aiQuaterniont<TReal>& rotation, aiVector3t<TReal>& position)
+inline aiMatrix4x4t<TReal>::aiMatrix4x4t (const aiVector3t<TReal>& scaling, const aiQuaterniont<TReal>& rotation, const aiVector3t<TReal>& position)
{
// build a 3x3 rotation matrix
aiMatrix3x3t<TReal> m = rotation.GetMatrix();
diff --git a/src/3rdparty/assimp/include/assimp/metadata.h b/src/3rdparty/assimp/include/assimp/metadata.h
index 8c8880e81..16809a511 100644
--- a/src/3rdparty/assimp/include/assimp/metadata.h
+++ b/src/3rdparty/assimp/include/assimp/metadata.h
@@ -48,7 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assert.h>
#if defined(_MSC_VER) && (_MSC_VER <= 1500)
-#include "pstdint.h"
+#include "Compiler/pstdint.h"
#else
#include <stdint.h>
#endif
diff --git a/src/3rdparty/assimp/include/assimp/quaternion.h b/src/3rdparty/assimp/include/assimp/quaternion.h
index a1fcbea9f..ad64dd9d3 100644
--- a/src/3rdparty/assimp/include/assimp/quaternion.h
+++ b/src/3rdparty/assimp/include/assimp/quaternion.h
@@ -55,7 +55,7 @@ template <typename TReal>
class aiQuaterniont
{
public:
- aiQuaterniont() : w(), x(), y(), z() {}
+ aiQuaterniont() : w(1.0), x(), y(), z() {}
aiQuaterniont(TReal pw, TReal px, TReal py, TReal pz)
: w(pw), x(px), y(py), z(pz) {}
diff --git a/src/3rdparty/assimp/include/assimp/vector3.h b/src/3rdparty/assimp/include/assimp/vector3.h
index c21e6cfde..8176f98a7 100644
--- a/src/3rdparty/assimp/include/assimp/vector3.h
+++ b/src/3rdparty/assimp/include/assimp/vector3.h
@@ -88,6 +88,7 @@ public:
// comparison
bool operator== (const aiVector3t& other) const;
bool operator!= (const aiVector3t& other) const;
+ bool operator < (const aiVector3t& other) const;
bool Equal(const aiVector3t& other, TReal epsilon = 1e-6) const;
diff --git a/src/3rdparty/assimp/include/assimp/vector3.inl b/src/3rdparty/assimp/include/assimp/vector3.inl
index b8cbe8b49..01e0b6f9d 100644
--- a/src/3rdparty/assimp/include/assimp/vector3.inl
+++ b/src/3rdparty/assimp/include/assimp/vector3.inl
@@ -159,6 +159,11 @@ AI_FORCE_INLINE bool aiVector3t<TReal>::Equal(const aiVector3t<TReal>& other, TR
}
// ------------------------------------------------------------------------------------------------
template <typename TReal>
+AI_FORCE_INLINE bool aiVector3t<TReal>::operator < (const aiVector3t<TReal>& other) const {
+ return x != other.x ? x < other.x : y != other.y ? y < other.y : z < other.z;
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
AI_FORCE_INLINE const aiVector3t<TReal> aiVector3t<TReal>::SymMul(const aiVector3t<TReal>& o) {
return aiVector3t<TReal>(x*o.x,y*o.y,z*o.z);
}
diff --git a/src/3rdparty/assimp/revision.h b/src/3rdparty/assimp/revision.h
index cebfa4b16..b265fb08f 100644
--- a/src/3rdparty/assimp/revision.h
+++ b/src/3rdparty/assimp/revision.h
@@ -1,6 +1,7 @@
#ifndef ASSIMP_REVISION_H_INC
#define ASSIMP_REVISION_H_INC
-#define GitVersion 0xA0bA3A8;
+#define GitVersion 0x1c4a8e9
+#define GitBranch "master"
#endif // ASSIMP_REVISION_H_INC