Browse Source

Merge pull request #44599 from RevoluPowered/remove_assimp_fbx

[fbx] remove old assimp plugin - pending fbx upgrade
Rémi Verschelde 4 years ago
parent
commit
a003ff0cf2
100 changed files with 0 additions and 34888 deletions
  1. 0 108
      modules/assimp/SCsub
  2. 0 6
      modules/assimp/config.py
  3. 0 1485
      modules/assimp/editor_scene_importer_assimp.cpp
  4. 0 149
      modules/assimp/editor_scene_importer_assimp.h
  5. 0 262
      modules/assimp/godot_update_assimp.sh
  6. 0 132
      modules/assimp/import_state.h
  7. 0 463
      modules/assimp/import_utils.h
  8. 0 58
      modules/assimp/register_types.cpp
  9. 0 37
      modules/assimp/register_types.h
  10. 0 18
      thirdparty/README.md
  11. 0 183
      thirdparty/assimp/CREDITS
  12. 0 78
      thirdparty/assimp/LICENSE
  13. 0 156
      thirdparty/assimp/code/CApi/AssimpCExport.cpp
  14. 0 136
      thirdparty/assimp/code/CApi/CInterfaceIOWrapper.cpp
  15. 0 99
      thirdparty/assimp/code/CApi/CInterfaceIOWrapper.h
  16. 0 695
      thirdparty/assimp/code/Common/Assimp.cpp
  17. 0 656
      thirdparty/assimp/code/Common/BaseImporter.cpp
  18. 0 107
      thirdparty/assimp/code/Common/BaseProcess.cpp
  19. 0 290
      thirdparty/assimp/code/Common/BaseProcess.h
  20. 0 155
      thirdparty/assimp/code/Common/Bitmap.cpp
  21. 0 88
      thirdparty/assimp/code/Common/CreateAnimMesh.cpp
  22. 0 154
      thirdparty/assimp/code/Common/DefaultIOStream.cpp
  23. 0 216
      thirdparty/assimp/code/Common/DefaultIOSystem.cpp
  24. 0 418
      thirdparty/assimp/code/Common/DefaultLogger.cpp
  25. 0 65
      thirdparty/assimp/code/Common/DefaultProgressHandler.h
  26. 0 636
      thirdparty/assimp/code/Common/Exporter.cpp
  27. 0 107
      thirdparty/assimp/code/Common/FileLogStream.h
  28. 0 345
      thirdparty/assimp/code/Common/FileSystemFilter.h
  29. 0 102
      thirdparty/assimp/code/Common/IFF.h
  30. 0 1174
      thirdparty/assimp/code/Common/Importer.cpp
  31. 0 247
      thirdparty/assimp/code/Common/Importer.h
  32. 0 377
      thirdparty/assimp/code/Common/ImporterRegistry.cpp
  33. 0 229
      thirdparty/assimp/code/Common/PolyTools.h
  34. 0 265
      thirdparty/assimp/code/Common/PostStepRegistry.cpp
  35. 0 113
      thirdparty/assimp/code/Common/RemoveComments.cpp
  36. 0 168
      thirdparty/assimp/code/Common/SGSpatialSort.cpp
  37. 0 1350
      thirdparty/assimp/code/Common/SceneCombiner.cpp
  38. 0 261
      thirdparty/assimp/code/Common/ScenePreprocessor.cpp
  39. 0 125
      thirdparty/assimp/code/Common/ScenePreprocessor.h
  40. 0 105
      thirdparty/assimp/code/Common/ScenePrivate.h
  41. 0 270
      thirdparty/assimp/code/Common/SkeletonMeshBuilder.cpp
  42. 0 342
      thirdparty/assimp/code/Common/SpatialSort.cpp
  43. 0 407
      thirdparty/assimp/code/Common/SplitByBoneCountProcess.cpp
  44. 0 111
      thirdparty/assimp/code/Common/SplitByBoneCountProcess.h
  45. 0 507
      thirdparty/assimp/code/Common/StandardShapes.cpp
  46. 0 101
      thirdparty/assimp/code/Common/StdOStreamLogStream.h
  47. 0 589
      thirdparty/assimp/code/Common/Subdivision.cpp
  48. 0 248
      thirdparty/assimp/code/Common/TargetAnimation.cpp
  49. 0 183
      thirdparty/assimp/code/Common/TargetAnimation.h
  50. 0 181
      thirdparty/assimp/code/Common/Version.cpp
  51. 0 134
      thirdparty/assimp/code/Common/VertexTriangleAdjacency.cpp
  52. 0 117
      thirdparty/assimp/code/Common/VertexTriangleAdjacency.h
  53. 0 95
      thirdparty/assimp/code/Common/Win32DebugLogStream.h
  54. 0 196
      thirdparty/assimp/code/Common/assbin_chunks.h
  55. 0 140
      thirdparty/assimp/code/Common/scene.cpp
  56. 0 79
      thirdparty/assimp/code/Common/simd.cpp
  57. 0 53
      thirdparty/assimp/code/Common/simd.h
  58. 0 305
      thirdparty/assimp/code/FBX/FBXAnimation.cpp
  59. 0 466
      thirdparty/assimp/code/FBX/FBXBinaryTokenizer.cpp
  60. 0 86
      thirdparty/assimp/code/FBX/FBXCommon.h
  61. 0 78
      thirdparty/assimp/code/FBX/FBXCompileConfig.h
  62. 0 3727
      thirdparty/assimp/code/FBX/FBXConverter.cpp
  63. 0 491
      thirdparty/assimp/code/FBX/FBXConverter.h
  64. 0 213
      thirdparty/assimp/code/FBX/FBXDeformer.cpp
  65. 0 718
      thirdparty/assimp/code/FBX/FBXDocument.cpp
  66. 0 1215
      thirdparty/assimp/code/FBX/FBXDocument.h
  67. 0 135
      thirdparty/assimp/code/FBX/FBXDocumentUtil.cpp
  68. 0 120
      thirdparty/assimp/code/FBX/FBXDocumentUtil.h
  69. 0 571
      thirdparty/assimp/code/FBX/FBXExportNode.cpp
  70. 0 271
      thirdparty/assimp/code/FBX/FBXExportNode.h
  71. 0 385
      thirdparty/assimp/code/FBX/FBXExportProperty.cpp
  72. 0 129
      thirdparty/assimp/code/FBX/FBXExportProperty.h
  73. 0 2556
      thirdparty/assimp/code/FBX/FBXExporter.cpp
  74. 0 178
      thirdparty/assimp/code/FBX/FBXExporter.h
  75. 0 164
      thirdparty/assimp/code/FBX/FBXImportSettings.h
  76. 0 198
      thirdparty/assimp/code/FBX/FBXImporter.cpp
  77. 0 100
      thirdparty/assimp/code/FBX/FBXImporter.h
  78. 0 405
      thirdparty/assimp/code/FBX/FBXMaterial.cpp
  79. 0 709
      thirdparty/assimp/code/FBX/FBXMeshGeometry.cpp
  80. 0 235
      thirdparty/assimp/code/FBX/FBXMeshGeometry.h
  81. 0 153
      thirdparty/assimp/code/FBX/FBXModel.cpp
  82. 0 170
      thirdparty/assimp/code/FBX/FBXNodeAttribute.cpp
  83. 0 1309
      thirdparty/assimp/code/FBX/FBXParser.cpp
  84. 0 235
      thirdparty/assimp/code/FBX/FBXParser.h
  85. 0 235
      thirdparty/assimp/code/FBX/FBXProperties.cpp
  86. 0 185
      thirdparty/assimp/code/FBX/FBXProperties.h
  87. 0 248
      thirdparty/assimp/code/FBX/FBXTokenizer.cpp
  88. 0 187
      thirdparty/assimp/code/FBX/FBXTokenizer.h
  89. 0 243
      thirdparty/assimp/code/FBX/FBXUtil.cpp
  90. 0 137
      thirdparty/assimp/code/FBX/FBXUtil.h
  91. 0 632
      thirdparty/assimp/code/Material/MaterialSystem.cpp
  92. 0 72
      thirdparty/assimp/code/Material/MaterialSystem.h
  93. 0 268
      thirdparty/assimp/code/PostProcessing/ArmaturePopulate.cpp
  94. 0 112
      thirdparty/assimp/code/PostProcessing/ArmaturePopulate.h
  95. 0 319
      thirdparty/assimp/code/PostProcessing/CalcTangentsProcess.cpp
  96. 0 117
      thirdparty/assimp/code/PostProcessing/CalcTangentsProcess.h
  97. 0 506
      thirdparty/assimp/code/PostProcessing/ComputeUVMappingProcess.cpp
  98. 0 149
      thirdparty/assimp/code/PostProcessing/ComputeUVMappingProcess.h
  99. 0 414
      thirdparty/assimp/code/PostProcessing/ConvertToLHProcess.cpp
  100. 0 171
      thirdparty/assimp/code/PostProcessing/ConvertToLHProcess.h

+ 0 - 108
modules/assimp/SCsub

@@ -1,108 +0,0 @@
-#!/usr/bin/env python
-
-Import("env")
-Import("env_modules")
-
-env_assimp = env_modules.Clone()
-
-# Thirdparty source files
-
-thirdparty_obj = []
-
-# Force bundled version for now, there's no released version of Assimp with
-# support for ArmaturePopulate which we use from their master branch.
-
-if True:  # env['builtin_assimp']:
-    thirdparty_dir = "#thirdparty/assimp"
-
-    env_assimp.Prepend(CPPPATH=["#thirdparty/assimp"])
-    env_assimp.Prepend(CPPPATH=["#thirdparty/assimp/code"])
-    env_assimp.Prepend(CPPPATH=["#thirdparty/assimp/include"])
-
-    # env_assimp.Append(CPPDEFINES=['ASSIMP_DOUBLE_PRECISION']) # TODO default to what godot is compiled with for future double support
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_SINGLETHREADED"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_BOOST_WORKAROUND"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_OWN_ZLIB"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_EXPORT"])
-
-    # Importers we don't need
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_3D_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_3DS_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_3MF_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_AC_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_AMF_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_ASE_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_ASSBIN_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_B3D_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_BLEND_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_BVH_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_C4D_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_COB_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_COLLADA_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_CSM_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_DXF_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_GLTF2_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_GLTF_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_HMP_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_IFC_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_IRR_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_IRRMESH_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_LWO_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_LWS_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_M3D_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_MD2_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_MD3_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_MD5_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_MD5_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_MDC_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_MDL_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_MMD_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_MS3D_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_NDO_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_NFF_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_OBJ_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_OFF_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_OGRE_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_OPENGEX_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_PLY_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_Q3BSP_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_Q3D_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_RAW_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_SIB_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_SMD_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_STEP_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_STL_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_TERRAGEN_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_X3D_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_XGL_IMPORTER"])
-    env_assimp.Append(CPPDEFINES=["ASSIMP_BUILD_NO_X_IMPORTER"])
-
-    if env["platform"] == "windows":
-        env_assimp.Append(CPPDEFINES=["PLATFORM_WINDOWS"])
-        env_assimp.Append(CPPDEFINES=[("PLATFORM", "WINDOWS")])
-    elif env["platform"] == "linuxbsd":
-        env_assimp.Append(CPPDEFINES=["PLATFORM_LINUX"])
-        env_assimp.Append(CPPDEFINES=[("PLATFORM", "LINUX")])
-    elif env["platform"] == "osx":
-        env_assimp.Append(CPPDEFINES=["PLATFORM_DARWIN"])
-        env_assimp.Append(CPPDEFINES=[("PLATFORM", "DARWIN")])
-
-    env_thirdparty = env_assimp.Clone()
-    env_thirdparty.disable_warnings()
-    env_thirdparty.add_source_files(thirdparty_obj, Glob("#thirdparty/assimp/code/CApi/*.cpp"))
-    env_thirdparty.add_source_files(thirdparty_obj, Glob("#thirdparty/assimp/code/Common/*.cpp"))
-    env_thirdparty.add_source_files(thirdparty_obj, Glob("#thirdparty/assimp/code/PostProcessing/*.cpp"))
-    env_thirdparty.add_source_files(thirdparty_obj, Glob("#thirdparty/assimp/code/Material/*.cpp"))
-    env_thirdparty.add_source_files(thirdparty_obj, Glob("#thirdparty/assimp/code/FBX/*.cpp"))
-    env.modules_sources += thirdparty_obj
-
-
-# Godot source files
-
-module_obj = []
-
-env_assimp.add_source_files(module_obj, "*.cpp")
-env.modules_sources += module_obj
-
-# Needed to force rebuilding the module files when the thirdparty library is updated.
-env.Depends(module_obj, thirdparty_obj)

+ 0 - 6
modules/assimp/config.py

@@ -1,6 +0,0 @@
-def can_build(env, platform):
-    return env["tools"]
-
-
-def configure(env):
-    pass

+ 0 - 1485
modules/assimp/editor_scene_importer_assimp.cpp

@@ -1,1485 +0,0 @@
-/*************************************************************************/
-/*  editor_scene_importer_assimp.cpp                                     */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the       */
-/* "Software"), to deal in the Software without restriction, including   */
-/* without limitation the rights to use, copy, modify, merge, publish,   */
-/* distribute, sublicense, and/or sell copies of the Software, and to    */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions:                                             */
-/*                                                                       */
-/* The above copyright notice and this permission notice shall be        */
-/* included in all copies or substantial portions of the Software.       */
-/*                                                                       */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
-/*************************************************************************/
-
-#include "editor_scene_importer_assimp.h"
-#include "core/io/image_loader.h"
-#include "editor/import/resource_importer_scene.h"
-#include "import_utils.h"
-#include "scene/3d/camera_3d.h"
-#include "scene/3d/light_3d.h"
-#include "scene/3d/mesh_instance_3d.h"
-#include "scene/main/node.h"
-#include "scene/resources/material.h"
-#include "scene/resources/surface_tool.h"
-
-#include <assimp/matrix4x4.h>
-#include <assimp/postprocess.h>
-#include <assimp/scene.h>
-#include <assimp/Importer.hpp>
-#include <assimp/LogStream.hpp>
-
-// move into assimp
-aiBone *get_bone_by_name(const aiScene *scene, aiString bone_name) {
-	for (unsigned int mesh_id = 0; mesh_id < scene->mNumMeshes; ++mesh_id) {
-		aiMesh *mesh = scene->mMeshes[mesh_id];
-
-		// iterate over all the bones on the mesh for this node only!
-		for (unsigned int boneIndex = 0; boneIndex < mesh->mNumBones; boneIndex++) {
-			aiBone *bone = mesh->mBones[boneIndex];
-			if (bone->mName == bone_name) {
-				printf("matched bone by name: %s\n", bone->mName.C_Str());
-				return bone;
-			}
-		}
-	}
-
-	return nullptr;
-}
-
-void EditorSceneImporterAssimp::get_extensions(List<String> *r_extensions) const {
-	const String import_setting_string = "filesystem/import/open_asset_import/";
-
-	Map<String, ImportFormat> import_format;
-	{
-		Vector<String> exts;
-		exts.push_back("fbx");
-		ImportFormat import = { exts, true };
-		import_format.insert("fbx", import);
-	}
-	for (Map<String, ImportFormat>::Element *E = import_format.front(); E; E = E->next()) {
-		_register_project_setting_import(E->key(), import_setting_string, E->get().extensions, r_extensions,
-				E->get().is_default);
-	}
-}
-
-void EditorSceneImporterAssimp::_register_project_setting_import(const String generic, const String import_setting_string,
-		const Vector<String> &exts, List<String> *r_extensions,
-		const bool p_enabled) const {
-	const String use_generic = "use_" + generic;
-	_GLOBAL_DEF(import_setting_string + use_generic, p_enabled, true);
-	if (ProjectSettings::get_singleton()->get(import_setting_string + use_generic)) {
-		for (int32_t i = 0; i < exts.size(); i++) {
-			r_extensions->push_back(exts[i]);
-		}
-	}
-}
-
-uint32_t EditorSceneImporterAssimp::get_import_flags() const {
-	return IMPORT_SCENE;
-}
-
-void EditorSceneImporterAssimp::_bind_methods() {
-}
-
-Node *EditorSceneImporterAssimp::import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps,
-		List<String> *r_missing_deps, Error *r_err) {
-	Assimp::Importer importer;
-	importer.SetPropertyBool(AI_CONFIG_PP_FD_REMOVE, true);
-	// Cannot remove pivot points because the static mesh will be in the wrong place
-	importer.SetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, false);
-	int32_t max_bone_weights = 4;
-	//if (p_flags & IMPORT_ANIMATION_EIGHT_WEIGHTS) {
-	//	const int eight_bones = 8;
-	//	importer.SetPropertyBool(AI_CONFIG_PP_LBW_MAX_WEIGHTS, eight_bones);
-	//	max_bone_weights = eight_bones;
-	//}
-
-	importer.SetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE, aiPrimitiveType_LINE | aiPrimitiveType_POINT);
-
-	//importer.SetPropertyFloat(AI_CONFIG_PP_DB_THRESHOLD, 1.0f);
-	int32_t post_process_Steps = aiProcess_CalcTangentSpace |
-								 aiProcess_GlobalScale |
-								 // imports models and listens to their file scale for CM to M conversions
-								 //aiProcess_FlipUVs |
-								 aiProcess_FlipWindingOrder |
-								 // very important for culling so that it is done in the correct order.
-								 //aiProcess_DropNormals |
-								 //aiProcess_GenSmoothNormals |
-								 //aiProcess_JoinIdenticalVertices |
-								 aiProcess_ImproveCacheLocality |
-								 //aiProcess_RemoveRedundantMaterials | // Causes a crash
-								 //aiProcess_SplitLargeMeshes |
-								 aiProcess_Triangulate |
-								 aiProcess_GenUVCoords |
-								 //aiProcess_FindDegenerates |
-								 //aiProcess_SortByPType |
-								 // aiProcess_FindInvalidData |
-								 aiProcess_TransformUVCoords |
-								 aiProcess_FindInstances |
-								 //aiProcess_FixInfacingNormals |
-								 //aiProcess_ValidateDataStructure |
-								 aiProcess_OptimizeMeshes |
-								 aiProcess_PopulateArmatureData |
-								 //aiProcess_OptimizeGraph |
-								 //aiProcess_Debone |
-								 // aiProcess_EmbedTextures |
-								 //aiProcess_SplitByBoneCount |
-								 0;
-	String g_path = ProjectSettings::get_singleton()->globalize_path(p_path);
-	aiScene *scene = (aiScene *)importer.ReadFile(g_path.utf8().ptr(), post_process_Steps);
-
-	ERR_FAIL_COND_V_MSG(scene == nullptr, nullptr, String("Open Asset Import failed to open: ") + String(importer.GetErrorString()));
-
-	return _generate_scene(p_path, scene, p_flags, p_bake_fps, max_bone_weights);
-}
-
-template <class T>
-struct EditorSceneImporterAssetImportInterpolate {
-	T lerp(const T &a, const T &b, float c) const {
-		return a + (b - a) * c;
-	}
-
-	T catmull_rom(const T &p0, const T &p1, const T &p2, const T &p3, float t) {
-		float t2 = t * t;
-		float t3 = t2 * t;
-
-		return 0.5f * ((2.0f * p1) + (-p0 + p2) * t + (2.0f * p0 - 5.0f * p1 + 4.0f * p2 - p3) * t2 + (-p0 + 3.0f * p1 - 3.0f * p2 + p3) * t3);
-	}
-
-	T bezier(T start, T control_1, T control_2, T end, float t) {
-		/* Formula from Wikipedia article on Bezier curves. */
-		real_t omt = (1.0 - t);
-		real_t omt2 = omt * omt;
-		real_t omt3 = omt2 * omt;
-		real_t t2 = t * t;
-		real_t t3 = t2 * t;
-
-		return start * omt3 + control_1 * omt2 * t * 3.0 + control_2 * omt * t2 * 3.0 + end * t3;
-	}
-};
-
-//thank you for existing, partial specialization
-template <>
-struct EditorSceneImporterAssetImportInterpolate<Quat> {
-	Quat lerp(const Quat &a, const Quat &b, float c) const {
-		ERR_FAIL_COND_V_MSG(!a.is_normalized(), Quat(), "The quaternion \"a\" must be normalized.");
-		ERR_FAIL_COND_V_MSG(!b.is_normalized(), Quat(), "The quaternion \"b\" must be normalized.");
-
-		return a.slerp(b, c).normalized();
-	}
-
-	Quat catmull_rom(const Quat &p0, const Quat &p1, const Quat &p2, const Quat &p3, float c) {
-		ERR_FAIL_COND_V_MSG(!p1.is_normalized(), Quat(), "The quaternion \"p1\" must be normalized.");
-		ERR_FAIL_COND_V_MSG(!p2.is_normalized(), Quat(), "The quaternion \"p2\" must be normalized.");
-
-		return p1.slerp(p2, c).normalized();
-	}
-
-	Quat bezier(Quat start, Quat control_1, Quat control_2, Quat end, float t) {
-		ERR_FAIL_COND_V_MSG(!start.is_normalized(), Quat(), "The start quaternion must be normalized.");
-		ERR_FAIL_COND_V_MSG(!end.is_normalized(), Quat(), "The end quaternion must be normalized.");
-
-		return start.slerp(end, t).normalized();
-	}
-};
-
-template <class T>
-T EditorSceneImporterAssimp::_interpolate_track(const Vector<float> &p_times, const Vector<T> &p_values, float p_time,
-		AssetImportAnimation::Interpolation p_interp) {
-	//could use binary search, worth it?
-	int idx = -1;
-	for (int i = 0; i < p_times.size(); i++) {
-		if (p_times[i] > p_time) {
-			break;
-		}
-		idx++;
-	}
-
-	EditorSceneImporterAssetImportInterpolate<T> interp;
-
-	switch (p_interp) {
-		case AssetImportAnimation::INTERP_LINEAR: {
-			if (idx == -1) {
-				return p_values[0];
-			} else if (idx >= p_times.size() - 1) {
-				return p_values[p_times.size() - 1];
-			}
-
-			float c = (p_time - p_times[idx]) / (p_times[idx + 1] - p_times[idx]);
-
-			return interp.lerp(p_values[idx], p_values[idx + 1], c);
-
-		} break;
-		case AssetImportAnimation::INTERP_STEP: {
-			if (idx == -1) {
-				return p_values[0];
-			} else if (idx >= p_times.size() - 1) {
-				return p_values[p_times.size() - 1];
-			}
-
-			return p_values[idx];
-
-		} break;
-		case AssetImportAnimation::INTERP_CATMULLROMSPLINE: {
-			if (idx == -1) {
-				return p_values[1];
-			} else if (idx >= p_times.size() - 1) {
-				return p_values[1 + p_times.size() - 1];
-			}
-
-			float c = (p_time - p_times[idx]) / (p_times[idx + 1] - p_times[idx]);
-
-			return interp.catmull_rom(p_values[idx - 1], p_values[idx], p_values[idx + 1], p_values[idx + 3], c);
-
-		} break;
-		case AssetImportAnimation::INTERP_CUBIC_SPLINE: {
-			if (idx == -1) {
-				return p_values[1];
-			} else if (idx >= p_times.size() - 1) {
-				return p_values[(p_times.size() - 1) * 3 + 1];
-			}
-
-			float c = (p_time - p_times[idx]) / (p_times[idx + 1] - p_times[idx]);
-
-			T from = p_values[idx * 3 + 1];
-			T c1 = from + p_values[idx * 3 + 2];
-			T to = p_values[idx * 3 + 4];
-			T c2 = to + p_values[idx * 3 + 3];
-
-			return interp.bezier(from, c1, c2, to, c);
-
-		} break;
-	}
-
-	ERR_FAIL_V(p_values[0]);
-}
-
-aiBone *EditorSceneImporterAssimp::get_bone_from_stack(ImportState &state, aiString name) {
-	List<aiBone *>::Element *iter;
-	aiBone *bone = nullptr;
-	for (iter = state.bone_stack.front(); iter; iter = iter->next()) {
-		bone = (aiBone *)iter->get();
-
-		if (bone && bone->mName == name) {
-			state.bone_stack.erase(bone);
-			return bone;
-		}
-	}
-
-	return nullptr;
-}
-
-Node3D *
-EditorSceneImporterAssimp::_generate_scene(const String &p_path, aiScene *scene, const uint32_t p_flags, int p_bake_fps,
-		const int32_t p_max_bone_weights) {
-	ERR_FAIL_COND_V(scene == nullptr, nullptr);
-
-	ImportState state;
-	state.path = p_path;
-	state.assimp_scene = scene;
-	state.max_bone_weights = p_max_bone_weights;
-	state.animation_player = nullptr;
-	state.import_flags = p_flags;
-
-	// populate light map
-	for (unsigned int l = 0; l < scene->mNumLights; l++) {
-		aiLight *ai_light = scene->mLights[l];
-		ERR_CONTINUE(ai_light == nullptr);
-		state.light_cache[AssimpUtils::get_assimp_string(ai_light->mName)] = l;
-	}
-
-	// fill camera cache
-	for (unsigned int c = 0; c < scene->mNumCameras; c++) {
-		aiCamera *ai_camera = scene->mCameras[c];
-		ERR_CONTINUE(ai_camera == nullptr);
-		state.camera_cache[AssimpUtils::get_assimp_string(ai_camera->mName)] = c;
-	}
-
-	if (scene->mRootNode) {
-		state.nodes.push_back(scene->mRootNode);
-
-		// make flat node tree - in order to make processing deterministic
-		for (unsigned int i = 0; i < scene->mRootNode->mNumChildren; i++) {
-			_generate_node(state, scene->mRootNode->mChildren[i]);
-		}
-
-		RegenerateBoneStack(state);
-
-		Node *last_valid_parent = nullptr;
-
-		List<const aiNode *>::Element *iter;
-		for (iter = state.nodes.front(); iter; iter = iter->next()) {
-			const aiNode *element_assimp_node = iter->get();
-			const aiNode *parent_assimp_node = element_assimp_node->mParent;
-
-			String node_name = AssimpUtils::get_assimp_string(element_assimp_node->mName);
-			//print_verbose("node: " + node_name);
-
-			Node3D *spatial = nullptr;
-			Transform transform = AssimpUtils::assimp_matrix_transform(element_assimp_node->mTransformation);
-
-			// retrieve this node bone
-			aiBone *bone = get_bone_from_stack(state, element_assimp_node->mName);
-
-			if (state.light_cache.has(node_name)) {
-				spatial = create_light(state, node_name, transform);
-			} else if (state.camera_cache.has(node_name)) {
-				spatial = create_camera(state, node_name, transform);
-			} else if (state.armature_nodes.find(element_assimp_node)) {
-				// create skeleton
-				print_verbose("Making skeleton: " + node_name);
-				Skeleton3D *skeleton = memnew(Skeleton3D);
-				spatial = skeleton;
-				if (!state.armature_skeletons.has(element_assimp_node)) {
-					state.armature_skeletons.insert(element_assimp_node, skeleton);
-				}
-			} else if (bone != nullptr) {
-				continue;
-			} else {
-				spatial = memnew(Node3D);
-			}
-
-			ERR_CONTINUE_MSG(spatial == nullptr, "FBX Import - are we out of ram?");
-			// we on purpose set the transform and name after creating the node.
-
-			spatial->set_name(node_name);
-			spatial->set_global_transform(transform);
-
-			// first element is root
-			if (iter == state.nodes.front()) {
-				state.root = spatial;
-			}
-
-			// flat node map parent lookup tool
-			state.flat_node_map.insert(element_assimp_node, spatial);
-
-			Map<const aiNode *, Node3D *>::Element *parent_lookup = state.flat_node_map.find(parent_assimp_node);
-
-			// note: this always fails on the root node :) keep that in mind this is by design
-			if (parent_lookup) {
-				Node3D *parent_node = parent_lookup->value();
-
-				ERR_FAIL_COND_V_MSG(parent_node == nullptr, state.root,
-						"Parent node invalid even though lookup successful, out of ram?");
-
-				if (spatial != state.root) {
-					parent_node->add_child(spatial);
-					spatial->set_owner(state.root);
-				} else {
-					// required - think about it root never has a parent yet is valid, anything else without a parent is not valid.
-				}
-			} else if (spatial != state.root) {
-				// if the ainode is not in the tree
-				// parent it to the last good parent found
-				if (last_valid_parent) {
-					last_valid_parent->add_child(spatial);
-					spatial->set_owner(state.root);
-				} else {
-					// this is a serious error?
-					memdelete(spatial);
-				}
-			}
-
-			// update last valid parent
-			last_valid_parent = spatial;
-		}
-		print_verbose("node counts: " + itos(state.nodes.size()));
-
-		// make clean bone stack
-		RegenerateBoneStack(state);
-
-		print_verbose("generating godot bone data");
-
-		print_verbose("Godot bone stack count: " + itos(state.bone_stack.size()));
-
-		// This is a list of bones, duplicates are from other meshes and must be dealt with properly
-		for (List<aiBone *>::Element *element = state.bone_stack.front(); element; element = element->next()) {
-			aiBone *bone = element->get();
-
-			ERR_CONTINUE_MSG(!bone, "invalid bone read from assimp?");
-
-			// Utilities for armature lookup - for now only FBX makes these
-			aiNode *armature_for_bone = bone->mArmature;
-
-			// Utilities for bone node lookup - for now only FBX makes these
-			aiNode *bone_node = bone->mNode;
-			aiNode *parent_node = bone_node->mParent;
-
-			String bone_name = AssimpUtils::get_anim_string_from_assimp(bone->mName);
-			ERR_CONTINUE_MSG(armature_for_bone == nullptr, "Armature for bone invalid: " + bone_name);
-			Skeleton3D *skeleton = state.armature_skeletons[armature_for_bone];
-
-			state.skeleton_bone_map[bone] = skeleton;
-
-			if (bone_name.empty()) {
-				bone_name = "untitled_bone_name";
-				WARN_PRINT("Untitled bone name detected... report with file please");
-			}
-
-			// todo: this is where skin support goes
-			if (skeleton && skeleton->find_bone(bone_name) == -1) {
-				print_verbose("[Godot Glue] Imported bone" + bone_name);
-				int boneIdx = skeleton->get_bone_count();
-
-				Transform pform = AssimpUtils::assimp_matrix_transform(bone->mNode->mTransformation);
-				skeleton->add_bone(bone_name);
-				skeleton->set_bone_rest(boneIdx, pform);
-
-				if (parent_node != nullptr) {
-					int parent_bone_id = skeleton->find_bone(AssimpUtils::get_anim_string_from_assimp(parent_node->mName));
-					int current_bone_id = boneIdx;
-					skeleton->set_bone_parent(current_bone_id, parent_bone_id);
-				}
-			}
-		}
-
-		print_verbose("generating mesh phase from skeletal mesh");
-
-		List<Node3D *> cleanup_template_nodes;
-
-		for (Map<const aiNode *, Node3D *>::Element *key_value_pair = state.flat_node_map.front(); key_value_pair; key_value_pair = key_value_pair->next()) {
-			const aiNode *assimp_node = key_value_pair->key();
-			Node3D *mesh_template = key_value_pair->value();
-
-			ERR_CONTINUE(assimp_node == nullptr);
-			ERR_CONTINUE(mesh_template == nullptr);
-
-			Node *parent_node = mesh_template->get_parent();
-
-			if (mesh_template == state.root) {
-				continue;
-			}
-
-			if (parent_node == nullptr) {
-				print_error("Found invalid parent node!");
-				continue; // root node
-			}
-
-			String node_name = AssimpUtils::get_assimp_string(assimp_node->mName);
-			Transform node_transform = AssimpUtils::assimp_matrix_transform(assimp_node->mTransformation);
-
-			if (assimp_node->mNumMeshes > 0) {
-				MeshInstance3D *mesh = create_mesh(state, assimp_node, node_name, parent_node, node_transform);
-				if (mesh) {
-					parent_node->remove_child(mesh_template);
-
-					// re-parent children
-					List<Node *> children;
-					// re-parent all children to new node
-					// note: since get_child_count will change during execution we must build a list first to be safe.
-					for (int childId = 0; childId < mesh_template->get_child_count(); childId++) {
-						// get child
-						Node *child = mesh_template->get_child(childId);
-						children.push_back(child);
-					}
-
-					for (List<Node *>::Element *element = children.front(); element; element = element->next()) {
-						// reparent the children to the real mesh node.
-						mesh_template->remove_child(element->get());
-						mesh->add_child(element->get());
-						element->get()->set_owner(state.root);
-					}
-
-					// update mesh in list so that each mesh node is available
-					// this makes the template unavailable which is the desired behaviour
-					state.flat_node_map[assimp_node] = mesh;
-
-					cleanup_template_nodes.push_back(mesh_template);
-
-					// clean up this list we don't need it
-					children.clear();
-				}
-			}
-		}
-
-		for (List<Node3D *>::Element *element = cleanup_template_nodes.front(); element; element = element->next()) {
-			if (element->get()) {
-				memdelete(element->get());
-			}
-		}
-	}
-
-	if (p_flags & IMPORT_ANIMATION && scene->mNumAnimations) {
-		state.animation_player = memnew(AnimationPlayer);
-		state.root->add_child(state.animation_player);
-		state.animation_player->set_owner(state.root);
-
-		for (uint32_t i = 0; i < scene->mNumAnimations; i++) {
-			_import_animation(state, i, p_bake_fps);
-		}
-	}
-
-	//
-	// Cleanup operations
-	//
-
-	state.mesh_cache.clear();
-	state.material_cache.clear();
-	state.light_cache.clear();
-	state.camera_cache.clear();
-	state.assimp_node_map.clear();
-	state.path_to_image_cache.clear();
-	state.nodes.clear();
-	state.flat_node_map.clear();
-	state.armature_skeletons.clear();
-	state.bone_stack.clear();
-	return state.root;
-}
-
-void EditorSceneImporterAssimp::_insert_animation_track(ImportState &scene, const aiAnimation *assimp_anim, int track_id,
-		int anim_fps, Ref<Animation> animation, float ticks_per_second,
-		Skeleton3D *skeleton, const NodePath &node_path,
-		const String &node_name, aiBone *track_bone) {
-	const aiNodeAnim *assimp_track = assimp_anim->mChannels[track_id];
-	//make transform track
-	int track_idx = animation->get_track_count();
-	animation->add_track(Animation::TYPE_TRANSFORM);
-	animation->track_set_path(track_idx, node_path);
-	//first determine animation length
-
-	float increment = 1.0 / float(anim_fps);
-	float time = 0.0;
-
-	bool last = false;
-
-	Vector<Vector3> pos_values;
-	Vector<float> pos_times;
-	Vector<Vector3> scale_values;
-	Vector<float> scale_times;
-	Vector<Quat> rot_values;
-	Vector<float> rot_times;
-
-	for (size_t p = 0; p < assimp_track->mNumPositionKeys; p++) {
-		aiVector3D pos = assimp_track->mPositionKeys[p].mValue;
-		pos_values.push_back(Vector3(pos.x, pos.y, pos.z));
-		pos_times.push_back(assimp_track->mPositionKeys[p].mTime / ticks_per_second);
-	}
-
-	for (size_t r = 0; r < assimp_track->mNumRotationKeys; r++) {
-		aiQuaternion quat = assimp_track->mRotationKeys[r].mValue;
-		rot_values.push_back(Quat(quat.x, quat.y, quat.z, quat.w).normalized());
-		rot_times.push_back(assimp_track->mRotationKeys[r].mTime / ticks_per_second);
-	}
-
-	for (size_t sc = 0; sc < assimp_track->mNumScalingKeys; sc++) {
-		aiVector3D scale = assimp_track->mScalingKeys[sc].mValue;
-		scale_values.push_back(Vector3(scale.x, scale.y, scale.z));
-		scale_times.push_back(assimp_track->mScalingKeys[sc].mTime / ticks_per_second);
-	}
-
-	while (true) {
-		Vector3 pos;
-		Quat rot;
-		Vector3 scale(1, 1, 1);
-
-		if (pos_values.size()) {
-			pos = _interpolate_track<Vector3>(pos_times, pos_values, time, AssetImportAnimation::INTERP_LINEAR);
-		}
-
-		if (rot_values.size()) {
-			rot = _interpolate_track<Quat>(rot_times, rot_values, time,
-					AssetImportAnimation::INTERP_LINEAR)
-						  .normalized();
-		}
-
-		if (scale_values.size()) {
-			scale = _interpolate_track<Vector3>(scale_times, scale_values, time, AssetImportAnimation::INTERP_LINEAR);
-		}
-
-		if (skeleton) {
-			int skeleton_bone = skeleton->find_bone(node_name);
-
-			if (skeleton_bone >= 0 && track_bone) {
-				Transform xform;
-				xform.basis.set_quat_scale(rot, scale);
-				xform.origin = pos;
-
-				xform = skeleton->get_bone_rest(skeleton_bone).inverse() * xform;
-
-				rot = xform.basis.get_rotation_quat();
-				rot.normalize();
-				scale = xform.basis.get_scale();
-				pos = xform.origin;
-			} else {
-				ERR_FAIL_MSG("Skeleton bone lookup failed for skeleton: " + skeleton->get_name());
-			}
-		}
-
-		animation->track_set_interpolation_type(track_idx, Animation::INTERPOLATION_LINEAR);
-		animation->transform_track_insert_key(track_idx, time, pos, rot, scale);
-
-		if (last) { //done this way so a key is always inserted past the end (for proper interpolation)
-			break;
-		}
-		time += increment;
-		if (time >= animation->get_length()) {
-			last = true;
-		}
-	}
-}
-
-// I really do not like this but need to figure out a better way of removing it later.
-Node *EditorSceneImporterAssimp::get_node_by_name(ImportState &state, String name) {
-	for (Map<const aiNode *, Node3D *>::Element *key_value_pair = state.flat_node_map.front(); key_value_pair; key_value_pair = key_value_pair->next()) {
-		const aiNode *assimp_node = key_value_pair->key();
-		Node3D *node = key_value_pair->value();
-
-		String node_name = AssimpUtils::get_assimp_string(assimp_node->mName);
-		if (name == node_name && node) {
-			return node;
-		}
-	}
-	return nullptr;
-}
-
-/* Bone stack is a fifo handler for multiple armatures since armatures aren't a thing in assimp (yet) */
-void EditorSceneImporterAssimp::RegenerateBoneStack(ImportState &state) {
-	state.bone_stack.clear();
-	// build bone stack list
-	for (unsigned int mesh_id = 0; mesh_id < state.assimp_scene->mNumMeshes; ++mesh_id) {
-		aiMesh *mesh = state.assimp_scene->mMeshes[mesh_id];
-
-		// iterate over all the bones on the mesh for this node only!
-		for (unsigned int boneIndex = 0; boneIndex < mesh->mNumBones; boneIndex++) {
-			aiBone *bone = mesh->mBones[boneIndex];
-
-			// doubtful this is required right now but best to check
-			if (!state.bone_stack.find(bone)) {
-				//print_verbose("[assimp] bone stack added: " + String(bone->mName.C_Str()) );
-				state.bone_stack.push_back(bone);
-			}
-		}
-	}
-}
-
-/* Bone stack is a fifo handler for multiple armatures since armatures aren't a thing in assimp (yet) */
-void EditorSceneImporterAssimp::RegenerateBoneStack(ImportState &state, aiMesh *mesh) {
-	state.bone_stack.clear();
-	// iterate over all the bones on the mesh for this node only!
-	for (unsigned int boneIndex = 0; boneIndex < mesh->mNumBones; boneIndex++) {
-		aiBone *bone = mesh->mBones[boneIndex];
-		if (state.bone_stack.find(bone) == nullptr) {
-			state.bone_stack.push_back(bone);
-		}
-	}
-}
-
-// animation tracks are per bone
-
-void EditorSceneImporterAssimp::_import_animation(ImportState &state, int p_animation_index, int p_bake_fps) {
-	ERR_FAIL_INDEX(p_animation_index, (int)state.assimp_scene->mNumAnimations);
-
-	const aiAnimation *anim = state.assimp_scene->mAnimations[p_animation_index];
-	String name = AssimpUtils::get_anim_string_from_assimp(anim->mName);
-	if (name == String()) {
-		name = "Animation " + itos(p_animation_index + 1);
-	}
-	print_verbose("import animation: " + name);
-	float ticks_per_second = anim->mTicksPerSecond;
-
-	if (state.assimp_scene->mMetaData != nullptr && Math::is_equal_approx(ticks_per_second, 0.0f)) {
-		int32_t time_mode = 0;
-		state.assimp_scene->mMetaData->Get("TimeMode", time_mode);
-		ticks_per_second = AssimpUtils::get_fbx_fps(time_mode, state.assimp_scene);
-	}
-
-	//?
-	//if ((p_path.get_file().get_extension().to_lower() == "glb" || p_path.get_file().get_extension().to_lower() == "gltf") && Math::is_equal_approx(ticks_per_second, 0.0f)) {
-	//	ticks_per_second = 1000.0f;
-	//}
-
-	if (Math::is_equal_approx(ticks_per_second, 0.0f)) {
-		ticks_per_second = 25.0f;
-	}
-
-	Ref<Animation> animation;
-	animation.instance();
-	animation->set_name(name);
-	animation->set_length(anim->mDuration / ticks_per_second);
-
-	if (name.begins_with("loop") || name.ends_with("loop") || name.begins_with("cycle") || name.ends_with("cycle")) {
-		animation->set_loop(true);
-	}
-
-	// generate bone stack for animation import
-	RegenerateBoneStack(state);
-
-	//regular tracks
-	for (size_t i = 0; i < anim->mNumChannels; i++) {
-		const aiNodeAnim *track = anim->mChannels[i];
-		String node_name = AssimpUtils::get_assimp_string(track->mNodeName);
-		print_verbose("track name import: " + node_name);
-		if (track->mNumRotationKeys == 0 && track->mNumPositionKeys == 0 && track->mNumScalingKeys == 0) {
-			continue; //do not bother
-		}
-
-		Skeleton3D *skeleton = nullptr;
-		NodePath node_path;
-		aiBone *bone = nullptr;
-
-		// Import skeleton bone animation for this track
-		// Any bone will do, no point in processing more than just what is in the skeleton
-		{
-			bone = get_bone_from_stack(state, track->mNodeName);
-
-			if (bone) {
-				// get skeleton by bone
-				skeleton = state.armature_skeletons[bone->mArmature];
-
-				if (skeleton) {
-					String path = state.root->get_path_to(skeleton);
-					path += ":" + node_name;
-					node_path = path;
-
-					if (node_path != NodePath()) {
-						_insert_animation_track(state, anim, i, p_bake_fps, animation, ticks_per_second, skeleton,
-								node_path, node_name, bone);
-					} else {
-						print_error("Failed to find valid node path for animation");
-					}
-				}
-			}
-		}
-
-		// not a bone
-		// note this is flaky it uses node names which is unreliable
-		Node *allocated_node = get_node_by_name(state, node_name);
-		// todo: implement skeleton grabbing for node based animations too :)
-		// check if node exists, if it does then also apply animation track for node and bones above are all handled.
-		// this is now inclusive animation handling so that
-		// we import all the data and do not miss anything.
-		if (allocated_node) {
-			node_path = state.root->get_path_to(allocated_node);
-
-			if (node_path != NodePath()) {
-				_insert_animation_track(state, anim, i, p_bake_fps, animation, ticks_per_second, skeleton,
-						node_path, node_name, nullptr);
-			}
-		}
-	}
-
-	//blend shape tracks
-
-	for (size_t i = 0; i < anim->mNumMorphMeshChannels; i++) {
-		const aiMeshMorphAnim *anim_mesh = anim->mMorphMeshChannels[i];
-
-		const String prop_name = AssimpUtils::get_assimp_string(anim_mesh->mName);
-		const String mesh_name = prop_name.split("*")[0];
-
-		ERR_CONTINUE(prop_name.split("*").size() != 2);
-
-		Node *item = get_node_by_name(state, mesh_name);
-		ERR_CONTINUE_MSG(!item, "failed to look up node by name");
-		const MeshInstance3D *mesh_instance = Object::cast_to<MeshInstance3D>(item);
-		ERR_CONTINUE(mesh_instance == nullptr);
-
-		String base_path = state.root->get_path_to(mesh_instance);
-
-		Ref<Mesh> mesh = mesh_instance->get_mesh();
-		ERR_CONTINUE(mesh.is_null());
-
-		//add the tracks for this mesh
-		int base_track = animation->get_track_count();
-		for (int j = 0; j < mesh->get_blend_shape_count(); j++) {
-			animation->add_track(Animation::TYPE_VALUE);
-			animation->track_set_path(base_track + j, base_path + ":blend_shapes/" + mesh->get_blend_shape_name(j));
-		}
-
-		for (size_t k = 0; k < anim_mesh->mNumKeys; k++) {
-			for (size_t j = 0; j < anim_mesh->mKeys[k].mNumValuesAndWeights; j++) {
-				float t = anim_mesh->mKeys[k].mTime / ticks_per_second;
-				float w = anim_mesh->mKeys[k].mWeights[j];
-
-				animation->track_insert_key(base_track + j, t, w);
-			}
-		}
-	}
-
-	if (animation->get_track_count()) {
-		state.animation_player->add_animation(name, animation);
-	}
-}
-
-//
-// Mesh Generation from indices ? why do we need so much mesh code
-// [debt needs looked into]
-Ref<Mesh>
-EditorSceneImporterAssimp::_generate_mesh_from_surface_indices(ImportState &state, const Vector<int> &p_surface_indices,
-		const aiNode *assimp_node, Ref<Skin> &skin,
-		Skeleton3D *&skeleton_assigned) {
-	Ref<ArrayMesh> mesh;
-	mesh.instance();
-	bool has_uvs = false;
-	uint32_t mesh_flags = 0;
-
-	Map<String, uint32_t> morph_mesh_string_lookup;
-
-	for (int i = 0; i < p_surface_indices.size(); i++) {
-		const unsigned int mesh_idx = p_surface_indices[0];
-		const aiMesh *ai_mesh = state.assimp_scene->mMeshes[mesh_idx];
-		for (size_t j = 0; j < ai_mesh->mNumAnimMeshes; j++) {
-			String ai_anim_mesh_name = AssimpUtils::get_assimp_string(ai_mesh->mAnimMeshes[j]->mName);
-			if (!morph_mesh_string_lookup.has(ai_anim_mesh_name)) {
-				morph_mesh_string_lookup.insert(ai_anim_mesh_name, j);
-				mesh->set_blend_shape_mode(ArrayMesh::BLEND_SHAPE_MODE_NORMALIZED);
-				if (ai_anim_mesh_name.empty()) {
-					ai_anim_mesh_name = String("morph_") + itos(j);
-				}
-				mesh->add_blend_shape(ai_anim_mesh_name);
-			}
-		}
-	}
-	//
-	// Process Vertex Weights
-	//
-	for (int i = 0; i < p_surface_indices.size(); i++) {
-		const unsigned int mesh_idx = p_surface_indices[i];
-		const aiMesh *ai_mesh = state.assimp_scene->mMeshes[mesh_idx];
-
-		Map<uint32_t, Vector<BoneInfo>> vertex_weights;
-
-		if (ai_mesh->mNumBones > 0) {
-			for (size_t b = 0; b < ai_mesh->mNumBones; b++) {
-				aiBone *bone = ai_mesh->mBones[b];
-
-				if (!skeleton_assigned) {
-					print_verbose("Assigned mesh skeleton during mesh creation");
-					skeleton_assigned = state.skeleton_bone_map[bone];
-
-					if (!skin.is_valid()) {
-						print_verbose("Configured new skin");
-						skin.instance();
-					} else {
-						print_verbose("Reusing existing skin!");
-					}
-				}
-				//                skeleton_assigned =
-				String bone_name = AssimpUtils::get_assimp_string(bone->mName);
-				int bone_index = skeleton_assigned->find_bone(bone_name);
-				ERR_CONTINUE(bone_index == -1);
-				for (size_t w = 0; w < bone->mNumWeights; w++) {
-					aiVertexWeight ai_weights = bone->mWeights[w];
-
-					BoneInfo bi;
-					uint32_t vertex_index = ai_weights.mVertexId;
-					bi.bone = bone_index;
-					bi.weight = ai_weights.mWeight;
-
-					if (!vertex_weights.has(vertex_index)) {
-						vertex_weights[vertex_index] = Vector<BoneInfo>();
-					}
-
-					vertex_weights[vertex_index].push_back(bi);
-				}
-			}
-		}
-
-		//
-		// Create mesh from data from assimp
-		//
-
-		Ref<SurfaceTool> st;
-		st.instance();
-		st->begin(Mesh::PRIMITIVE_TRIANGLES);
-
-		for (size_t j = 0; j < ai_mesh->mNumVertices; j++) {
-			// Get the texture coordinates if they exist
-			if (ai_mesh->HasTextureCoords(0)) {
-				has_uvs = true;
-				st->set_uv(Vector2(ai_mesh->mTextureCoords[0][j].x, 1.0f - ai_mesh->mTextureCoords[0][j].y));
-			}
-
-			if (ai_mesh->HasTextureCoords(1)) {
-				has_uvs = true;
-				st->set_uv2(Vector2(ai_mesh->mTextureCoords[1][j].x, 1.0f - ai_mesh->mTextureCoords[1][j].y));
-			}
-
-			// Assign vertex colors
-			if (ai_mesh->HasVertexColors(0)) {
-				Color color = Color(ai_mesh->mColors[0]->r, ai_mesh->mColors[0]->g, ai_mesh->mColors[0]->b,
-						ai_mesh->mColors[0]->a);
-				st->set_color(color);
-			}
-
-			// Work out normal calculations? - this needs work it doesn't work properly on huestos
-			if (ai_mesh->mNormals != nullptr) {
-				const aiVector3D normals = ai_mesh->mNormals[j];
-				const Vector3 godot_normal = Vector3(normals.x, normals.y, normals.z);
-				st->set_normal(godot_normal);
-				if (ai_mesh->HasTangentsAndBitangents()) {
-					const aiVector3D tangents = ai_mesh->mTangents[j];
-					const Vector3 godot_tangent = Vector3(tangents.x, tangents.y, tangents.z);
-					const aiVector3D bitangent = ai_mesh->mBitangents[j];
-					const Vector3 godot_bitangent = Vector3(bitangent.x, bitangent.y, bitangent.z);
-					float d = godot_normal.cross(godot_tangent).dot(godot_bitangent) > 0.0f ? 1.0f : -1.0f;
-					st->set_tangent(Plane(tangents.x, tangents.y, tangents.z, d));
-				}
-			}
-
-			// We have vertex weights right?
-			if (vertex_weights.has(j)) {
-				Vector<BoneInfo> bone_info = vertex_weights[j];
-				Vector<int> bones;
-				bones.resize(bone_info.size());
-				Vector<float> weights;
-				weights.resize(bone_info.size());
-
-				// todo? do we really need to loop over all bones? - assimp may have helper to find all influences on this vertex.
-				for (int k = 0; k < bone_info.size(); k++) {
-					bones.write[k] = bone_info[k].bone;
-					weights.write[k] = bone_info[k].weight;
-				}
-
-				st->set_bones(bones);
-				st->set_weights(weights);
-			}
-
-			// Assign vertex
-			const aiVector3D pos = ai_mesh->mVertices[j];
-
-			// note we must include node offset transform as this is relative to world space not local space.
-			Vector3 godot_pos = Vector3(pos.x, pos.y, pos.z);
-			st->add_vertex(godot_pos);
-		}
-
-		// fire replacement for face handling
-		for (size_t j = 0; j < ai_mesh->mNumFaces; j++) {
-			const aiFace face = ai_mesh->mFaces[j];
-			for (unsigned int k = 0; k < face.mNumIndices; k++) {
-				st->add_index(face.mIndices[k]);
-			}
-		}
-
-		if (ai_mesh->HasTangentsAndBitangents() == false && has_uvs) {
-			st->generate_tangents();
-		}
-
-		aiMaterial *ai_material = state.assimp_scene->mMaterials[ai_mesh->mMaterialIndex];
-		Ref<StandardMaterial3D> mat;
-		mat.instance();
-
-		int32_t mat_two_sided = 0;
-		if (AI_SUCCESS == ai_material->Get(AI_MATKEY_TWOSIDED, mat_two_sided)) {
-			if (mat_two_sided > 0) {
-				mat->set_cull_mode(StandardMaterial3D::CULL_DISABLED);
-			} else {
-				mat->set_cull_mode(StandardMaterial3D::CULL_BACK);
-			}
-		}
-
-		aiString mat_name;
-		if (AI_SUCCESS == ai_material->Get(AI_MATKEY_NAME, mat_name)) {
-			mat->set_name(AssimpUtils::get_assimp_string(mat_name));
-		}
-
-		// Culling handling for meshes
-
-		// cull all back faces
-		mat->set_cull_mode(StandardMaterial3D::CULL_DISABLED);
-
-		// Now process materials
-		aiTextureType base_color = aiTextureType_BASE_COLOR;
-		{
-			String filename, path;
-			AssimpImageData image_data;
-
-			if (AssimpUtils::GetAssimpTexture(state, ai_material, base_color, filename, path, image_data)) {
-				AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture);
-
-				// anything transparent must be culled
-				if (image_data.raw_image->detect_alpha() != Image::ALPHA_NONE) {
-					mat->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA_DEPTH_PRE_PASS);
-					mat->set_cull_mode(StandardMaterial3D::CULL_DISABLED); // since you can see both sides in transparent mode
-				}
-
-				mat->set_texture(StandardMaterial3D::TEXTURE_ALBEDO, image_data.texture);
-			}
-		}
-
-		aiTextureType tex_diffuse = aiTextureType_DIFFUSE;
-		{
-			String filename, path;
-			AssimpImageData image_data;
-
-			if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_diffuse, filename, path, image_data)) {
-				AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture);
-
-				// anything transparent must be culled
-				if (image_data.raw_image->detect_alpha() != Image::ALPHA_NONE) {
-					mat->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA_DEPTH_PRE_PASS);
-					mat->set_cull_mode(StandardMaterial3D::CULL_DISABLED); // since you can see both sides in transparent mode
-				}
-
-				mat->set_texture(StandardMaterial3D::TEXTURE_ALBEDO, image_data.texture);
-			}
-
-			aiColor4D clr_diffuse;
-			if (AI_SUCCESS == ai_material->Get(AI_MATKEY_COLOR_DIFFUSE, clr_diffuse)) {
-				if (Math::is_equal_approx(clr_diffuse.a, 1.0f) == false) {
-					mat->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA_DEPTH_PRE_PASS);
-					mat->set_cull_mode(StandardMaterial3D::CULL_DISABLED); // since you can see both sides in transparent mode
-				}
-				mat->set_albedo(Color(clr_diffuse.r, clr_diffuse.g, clr_diffuse.b, clr_diffuse.a));
-			}
-		}
-
-		aiTextureType tex_normal = aiTextureType_NORMALS;
-		{
-			String filename, path;
-			Ref<ImageTexture> texture;
-			AssimpImageData image_data;
-
-			// Process texture normal map
-			if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_normal, filename, path, image_data)) {
-				AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture);
-				mat->set_feature(StandardMaterial3D::Feature::FEATURE_NORMAL_MAPPING, true);
-				mat->set_texture(StandardMaterial3D::TEXTURE_NORMAL, image_data.texture);
-			} else {
-				aiString texture_path;
-				if (AI_SUCCESS == ai_material->Get(AI_MATKEY_FBX_NORMAL_TEXTURE, AI_PROPERTIES, texture_path)) {
-					if (AssimpUtils::CreateAssimpTexture(state, texture_path, filename, path, image_data)) {
-						mat->set_feature(StandardMaterial3D::Feature::FEATURE_NORMAL_MAPPING, true);
-						mat->set_texture(StandardMaterial3D::TEXTURE_NORMAL, image_data.texture);
-					}
-				}
-			}
-		}
-
-		aiTextureType tex_normal_camera = aiTextureType_NORMAL_CAMERA;
-		{
-			String filename, path;
-			Ref<ImageTexture> texture;
-			AssimpImageData image_data;
-
-			// Process texture normal map
-			if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_normal_camera, filename, path, image_data)) {
-				AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture);
-				mat->set_feature(StandardMaterial3D::Feature::FEATURE_NORMAL_MAPPING, true);
-				mat->set_texture(StandardMaterial3D::TEXTURE_NORMAL, image_data.texture);
-			}
-		}
-
-		aiTextureType tex_emission_color = aiTextureType_EMISSION_COLOR;
-		{
-			String filename, path;
-			Ref<ImageTexture> texture;
-			AssimpImageData image_data;
-
-			// Process texture normal map
-			if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_emission_color, filename, path, image_data)) {
-				AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture);
-				mat->set_feature(StandardMaterial3D::Feature::FEATURE_NORMAL_MAPPING, true);
-				mat->set_texture(StandardMaterial3D::TEXTURE_NORMAL, image_data.texture);
-			}
-		}
-
-		aiTextureType tex_metalness = aiTextureType_METALNESS;
-		{
-			String filename, path;
-			Ref<ImageTexture> texture;
-			AssimpImageData image_data;
-
-			// Process texture normal map
-			if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_metalness, filename, path, image_data)) {
-				AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture);
-				mat->set_texture(StandardMaterial3D::TEXTURE_METALLIC, image_data.texture);
-			}
-		}
-
-		aiTextureType tex_roughness = aiTextureType_DIFFUSE_ROUGHNESS;
-		{
-			String filename, path;
-			Ref<ImageTexture> texture;
-			AssimpImageData image_data;
-
-			// Process texture normal map
-			if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_roughness, filename, path, image_data)) {
-				AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture);
-				mat->set_texture(StandardMaterial3D::TEXTURE_ROUGHNESS, image_data.texture);
-			}
-		}
-
-		aiTextureType tex_emissive = aiTextureType_EMISSIVE;
-		{
-			String filename = "";
-			String path = "";
-			Ref<Image> texture;
-			AssimpImageData image_data;
-
-			if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_emissive, filename, path, image_data)) {
-				AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture);
-				mat->set_feature(StandardMaterial3D::FEATURE_EMISSION, true);
-				mat->set_texture(StandardMaterial3D::TEXTURE_EMISSION, image_data.texture);
-			} else {
-				// Process emission textures
-				aiString texture_emissive_path;
-				if (AI_SUCCESS ==
-						ai_material->Get(AI_MATKEY_FBX_MAYA_EMISSION_TEXTURE, AI_PROPERTIES, texture_emissive_path)) {
-					if (AssimpUtils::CreateAssimpTexture(state, texture_emissive_path, filename, path, image_data)) {
-						mat->set_feature(StandardMaterial3D::FEATURE_EMISSION, true);
-						mat->set_texture(StandardMaterial3D::TEXTURE_EMISSION, image_data.texture);
-					}
-				} else {
-					float pbr_emission = 0.0f;
-					if (AI_SUCCESS == ai_material->Get(AI_MATKEY_FBX_MAYA_EMISSIVE_FACTOR, AI_NULL, pbr_emission)) {
-						mat->set_emission(Color(pbr_emission, pbr_emission, pbr_emission, 1.0f));
-					}
-				}
-			}
-		}
-
-		aiTextureType tex_specular = aiTextureType_SPECULAR;
-		{
-			String filename, path;
-			Ref<ImageTexture> texture;
-			AssimpImageData image_data;
-
-			// Process texture normal map
-			if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_specular, filename, path, image_data)) {
-				AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture);
-				mat->set_texture(StandardMaterial3D::TEXTURE_METALLIC, image_data.texture);
-			}
-		}
-
-		aiTextureType tex_ao_map = aiTextureType_AMBIENT_OCCLUSION;
-		{
-			String filename, path;
-			Ref<ImageTexture> texture;
-			AssimpImageData image_data;
-
-			// Process texture normal map
-			if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_ao_map, filename, path, image_data)) {
-				AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture);
-				mat->set_feature(StandardMaterial3D::FEATURE_AMBIENT_OCCLUSION, true);
-				mat->set_texture(StandardMaterial3D::TEXTURE_AMBIENT_OCCLUSION, image_data.texture);
-			}
-		}
-
-		Array array_mesh = st->commit_to_arrays();
-		Array morphs;
-		morphs.resize(ai_mesh->mNumAnimMeshes);
-		Mesh::PrimitiveType primitive = Mesh::PRIMITIVE_TRIANGLES;
-
-		for (size_t j = 0; j < ai_mesh->mNumAnimMeshes; j++) {
-			String ai_anim_mesh_name = AssimpUtils::get_assimp_string(ai_mesh->mAnimMeshes[j]->mName);
-
-			if (ai_anim_mesh_name.empty()) {
-				ai_anim_mesh_name = String("morph_") + itos(j);
-			}
-
-			Array array_copy;
-			array_copy.resize(RenderingServer::ARRAY_MAX);
-
-			for (int l = 0; l < RenderingServer::ARRAY_MAX; l++) {
-				array_copy[l] = array_mesh[l].duplicate(true);
-			}
-
-			const size_t num_vertices = ai_mesh->mAnimMeshes[j]->mNumVertices;
-			array_copy[Mesh::ARRAY_INDEX] = Variant();
-			if (ai_mesh->mAnimMeshes[j]->HasPositions()) {
-				PackedVector3Array vertices;
-				vertices.resize(num_vertices);
-				for (size_t l = 0; l < num_vertices; l++) {
-					const aiVector3D ai_pos = ai_mesh->mAnimMeshes[j]->mVertices[l];
-					Vector3 position = Vector3(ai_pos.x, ai_pos.y, ai_pos.z);
-					vertices.ptrw()[l] = position;
-				}
-				PackedVector3Array new_vertices = array_copy[RenderingServer::ARRAY_VERTEX].duplicate(true);
-				ERR_CONTINUE(vertices.size() != new_vertices.size());
-				for (int32_t l = 0; l < new_vertices.size(); l++) {
-					Vector3 *w = new_vertices.ptrw();
-					w[l] = vertices[l];
-				}
-				array_copy[RenderingServer::ARRAY_VERTEX] = new_vertices;
-			}
-
-			int32_t color_set = 0;
-			if (ai_mesh->mAnimMeshes[j]->HasVertexColors(color_set)) {
-				PackedColorArray colors;
-				colors.resize(num_vertices);
-				for (size_t l = 0; l < num_vertices; l++) {
-					const aiColor4D ai_color = ai_mesh->mAnimMeshes[j]->mColors[color_set][l];
-					Color color = Color(ai_color.r, ai_color.g, ai_color.b, ai_color.a);
-					colors.ptrw()[l] = color;
-				}
-				PackedColorArray new_colors = array_copy[RenderingServer::ARRAY_COLOR].duplicate(true);
-				ERR_CONTINUE(colors.size() != new_colors.size());
-				for (int32_t l = 0; l < colors.size(); l++) {
-					Color *w = new_colors.ptrw();
-					w[l] = colors[l];
-				}
-				array_copy[RenderingServer::ARRAY_COLOR] = new_colors;
-			}
-
-			if (ai_mesh->mAnimMeshes[j]->HasNormals()) {
-				PackedVector3Array normals;
-				normals.resize(num_vertices);
-				for (size_t l = 0; l < num_vertices; l++) {
-					const aiVector3D ai_normal = ai_mesh->mAnimMeshes[j]->mNormals[l];
-					Vector3 normal = Vector3(ai_normal.x, ai_normal.y, ai_normal.z);
-					normals.ptrw()[l] = normal;
-				}
-				PackedVector3Array new_normals = array_copy[RenderingServer::ARRAY_NORMAL].duplicate(true);
-				ERR_CONTINUE(normals.size() != new_normals.size());
-				for (int l = 0; l < normals.size(); l++) {
-					Vector3 *w = new_normals.ptrw();
-					w[l] = normals[l];
-				}
-				array_copy[RenderingServer::ARRAY_NORMAL] = new_normals;
-			}
-
-			if (ai_mesh->mAnimMeshes[j]->HasTangentsAndBitangents()) {
-				PackedColorArray tangents;
-				tangents.resize(num_vertices);
-				Color *w = tangents.ptrw();
-				for (size_t l = 0; l < num_vertices; l++) {
-					AssimpUtils::calc_tangent_from_mesh(ai_mesh, j, l, l, w);
-				}
-				PackedFloat32Array new_tangents = array_copy[RenderingServer::ARRAY_TANGENT].duplicate(true);
-				ERR_CONTINUE(new_tangents.size() != tangents.size() * 4);
-				for (int32_t l = 0; l < tangents.size(); l++) {
-					new_tangents.ptrw()[l + 0] = tangents[l].r;
-					new_tangents.ptrw()[l + 1] = tangents[l].g;
-					new_tangents.ptrw()[l + 2] = tangents[l].b;
-					new_tangents.ptrw()[l + 3] = tangents[l].a;
-				}
-				array_copy[RenderingServer::ARRAY_TANGENT] = new_tangents;
-			}
-
-			morphs[j] = array_copy;
-		}
-		mesh->add_surface_from_arrays(primitive, array_mesh, morphs, Dictionary(), mesh_flags);
-		mesh->surface_set_material(i, mat);
-		mesh->surface_set_name(i, AssimpUtils::get_assimp_string(ai_mesh->mName));
-	}
-
-	return mesh;
-}
-
-/**
- * Create a new mesh for the node supplied
- */
-MeshInstance3D *
-EditorSceneImporterAssimp::create_mesh(ImportState &state, const aiNode *assimp_node, const String &node_name, Node *active_node, Transform node_transform) {
-	/* MESH NODE */
-	Ref<Mesh> mesh;
-	Ref<Skin> skin;
-	// see if we have mesh cache for this.
-	Vector<int> surface_indices;
-
-	RegenerateBoneStack(state);
-
-	// Configure indices
-	for (uint32_t i = 0; i < assimp_node->mNumMeshes; i++) {
-		int mesh_index = assimp_node->mMeshes[i];
-		// create list of mesh indexes
-		surface_indices.push_back(mesh_index);
-	}
-
-	//surface_indices.sort();
-	String mesh_key;
-	for (int i = 0; i < surface_indices.size(); i++) {
-		if (i > 0) {
-			mesh_key += ":";
-		}
-		mesh_key += itos(surface_indices[i]);
-	}
-
-	Skeleton3D *skeleton = nullptr;
-	aiNode *armature = nullptr;
-
-	if (!state.mesh_cache.has(mesh_key)) {
-		mesh = _generate_mesh_from_surface_indices(state, surface_indices, assimp_node, skin, skeleton);
-		state.mesh_cache[mesh_key] = mesh;
-	}
-
-	MeshInstance3D *mesh_node = memnew(MeshInstance3D);
-	mesh = state.mesh_cache[mesh_key];
-	mesh_node->set_mesh(mesh);
-
-	// if we have a valid skeleton set it up
-	if (skin.is_valid()) {
-		for (uint32_t i = 0; i < assimp_node->mNumMeshes; i++) {
-			unsigned int mesh_index = assimp_node->mMeshes[i];
-			const aiMesh *ai_mesh = state.assimp_scene->mMeshes[mesh_index];
-
-			// please remember bone id relative to the skin is NOT the mesh relative index.
-			// it is the index relative to the skeleton that is why
-			// we have state.bone_id_map, it allows for duplicate bone id's too :)
-			// hope this makes sense
-
-			int bind_count = 0;
-			for (unsigned int boneId = 0; boneId < ai_mesh->mNumBones; ++boneId) {
-				aiBone *iterBone = ai_mesh->mBones[boneId];
-
-				// used to reparent mesh to the correct armature later on if assigned.
-				if (!armature) {
-					print_verbose("Configured mesh armature, will reparent later to armature");
-					armature = iterBone->mArmature;
-				}
-
-				if (skeleton) {
-					int id = skeleton->find_bone(AssimpUtils::get_assimp_string(iterBone->mName));
-					if (id != -1) {
-						print_verbose("Set bind bone: mesh: " + itos(mesh_index) + " bone index: " + itos(id));
-						Transform t = AssimpUtils::assimp_matrix_transform(iterBone->mOffsetMatrix);
-
-						skin->add_bind(bind_count, t);
-						skin->set_bind_bone(bind_count, id);
-						bind_count++;
-					}
-				}
-			}
-		}
-
-		print_verbose("Finished configuring bind pose for skin mesh");
-	}
-
-	// this code parents all meshes with bones to the armature they are for
-	// GLTF2 specification relies on this and we are enforcing it for FBX.
-	if (armature && state.flat_node_map[armature]) {
-		Node *armature_parent = state.flat_node_map[armature];
-		print_verbose("Parented mesh " + node_name + " to armature " + armature_parent->get_name());
-		// static mesh handling
-		armature_parent->add_child(mesh_node);
-		// transform must be identity
-		mesh_node->set_global_transform(Transform());
-		mesh_node->set_name(node_name);
-		mesh_node->set_owner(state.root);
-	} else {
-		// static mesh handling
-		active_node->add_child(mesh_node);
-		mesh_node->set_global_transform(node_transform);
-		mesh_node->set_name(node_name);
-		mesh_node->set_owner(state.root);
-	}
-
-	if (skeleton) {
-		print_verbose("Attempted to set skeleton path!");
-		mesh_node->set_skeleton_path(mesh_node->get_path_to(skeleton));
-		mesh_node->set_skin(skin);
-	}
-
-	return mesh_node;
-}
-
-/**
- * Create a light for the scene
- * Automatically caches lights for lookup later
- */
-Node3D *EditorSceneImporterAssimp::create_light(
-		ImportState &state,
-		const String &node_name,
-		Transform &look_at_transform) {
-	Light3D *light = nullptr;
-	aiLight *assimp_light = state.assimp_scene->mLights[state.light_cache[node_name]];
-	ERR_FAIL_COND_V(!assimp_light, nullptr);
-
-	if (assimp_light->mType == aiLightSource_DIRECTIONAL) {
-		light = memnew(DirectionalLight3D);
-	} else if (assimp_light->mType == aiLightSource_POINT) {
-		light = memnew(OmniLight3D);
-	} else if (assimp_light->mType == aiLightSource_SPOT) {
-		light = memnew(SpotLight3D);
-	}
-	ERR_FAIL_COND_V(light == nullptr, nullptr);
-
-	if (assimp_light->mType != aiLightSource_POINT) {
-		Vector3 pos = Vector3(
-				assimp_light->mPosition.x,
-				assimp_light->mPosition.y,
-				assimp_light->mPosition.z);
-		Vector3 look_at = Vector3(
-				assimp_light->mDirection.y,
-				assimp_light->mDirection.x,
-				assimp_light->mDirection.z)
-								  .normalized();
-		Vector3 up = Vector3(
-				assimp_light->mUp.x,
-				assimp_light->mUp.y,
-				assimp_light->mUp.z);
-
-		look_at_transform.set_look_at(pos, look_at, up);
-	}
-	// properties for light variables should be put here.
-	// not really hugely important yet but we will need them in the future
-
-	light->set_color(
-			Color(assimp_light->mColorDiffuse.r, assimp_light->mColorDiffuse.g, assimp_light->mColorDiffuse.b));
-
-	return light;
-}
-
-/**
- * Create camera for the scene
- */
-Node3D *EditorSceneImporterAssimp::create_camera(
-		ImportState &state,
-		const String &node_name,
-		Transform &look_at_transform) {
-	aiCamera *camera = state.assimp_scene->mCameras[state.camera_cache[node_name]];
-	ERR_FAIL_COND_V(!camera, nullptr);
-
-	Camera3D *camera_node = memnew(Camera3D);
-	ERR_FAIL_COND_V(!camera_node, nullptr);
-	float near = camera->mClipPlaneNear;
-	if (Math::is_equal_approx(near, 0.0f)) {
-		near = 0.1f;
-	}
-	camera_node->set_perspective(Math::rad2deg(camera->mHorizontalFOV) * 2.0f, near, camera->mClipPlaneFar);
-	Vector3 pos = Vector3(camera->mPosition.x, camera->mPosition.y, camera->mPosition.z);
-	Vector3 look_at = Vector3(camera->mLookAt.y, camera->mLookAt.x, camera->mLookAt.z).normalized();
-	Vector3 up = Vector3(camera->mUp.x, camera->mUp.y, camera->mUp.z);
-
-	look_at_transform.set_look_at(pos + look_at_transform.origin, look_at, up);
-	return camera_node;
-}
-
-/**
- * Generate node
- * Recursive call to iterate over all nodes
- */
-void EditorSceneImporterAssimp::_generate_node(
-		ImportState &state,
-		const aiNode *assimp_node) {
-	ERR_FAIL_COND(assimp_node == nullptr);
-	state.nodes.push_back(assimp_node);
-	String parent_name = AssimpUtils::get_assimp_string(assimp_node->mParent->mName);
-
-	// please note
-	// duplicate bone names exist
-	// this is why we only check if the bone exists
-	// so everything else is useless but the name
-	// please do not copy any other values from get_bone_by_name.
-	aiBone *parent_bone = get_bone_by_name(state.assimp_scene, assimp_node->mParent->mName);
-	aiBone *current_bone = get_bone_by_name(state.assimp_scene, assimp_node->mName);
-
-	// is this an armature
-	// parent null
-	// and this is the first bone :)
-	if (parent_bone == nullptr && current_bone) {
-		state.armature_nodes.push_back(assimp_node->mParent);
-		print_verbose("found valid armature: " + parent_name);
-	}
-
-	for (size_t i = 0; i < assimp_node->mNumChildren; i++) {
-		_generate_node(state, assimp_node->mChildren[i]);
-	}
-}

+ 0 - 149
modules/assimp/editor_scene_importer_assimp.h

@@ -1,149 +0,0 @@
-/*************************************************************************/
-/*  editor_scene_importer_assimp.h                                       */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the       */
-/* "Software"), to deal in the Software without restriction, including   */
-/* without limitation the rights to use, copy, modify, merge, publish,   */
-/* distribute, sublicense, and/or sell copies of the Software, and to    */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions:                                             */
-/*                                                                       */
-/* The above copyright notice and this permission notice shall be        */
-/* included in all copies or substantial portions of the Software.       */
-/*                                                                       */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
-/*************************************************************************/
-
-#ifndef EDITOR_SCENE_IMPORTER_ASSIMP_H
-#define EDITOR_SCENE_IMPORTER_ASSIMP_H
-
-#ifdef TOOLS_ENABLED
-#include "core/core_bind.h"
-#include "core/io/resource_importer.h"
-#include "core/templates/vector.h"
-#include "editor/import/resource_importer_scene.h"
-#include "editor/project_settings_editor.h"
-#include "scene/3d/mesh_instance_3d.h"
-#include "scene/3d/node_3d.h"
-#include "scene/3d/skeleton_3d.h"
-#include "scene/animation/animation_player.h"
-#include "scene/resources/animation.h"
-#include "scene/resources/surface_tool.h"
-
-#include <assimp/matrix4x4.h>
-#include <assimp/scene.h>
-#include <assimp/types.h>
-#include <assimp/DefaultLogger.hpp>
-#include <assimp/LogStream.hpp>
-#include <assimp/Logger.hpp>
-#include <map>
-
-#include "import_state.h"
-#include "import_utils.h"
-
-using namespace AssimpImporter;
-
-class AssimpStream : public Assimp::LogStream {
-public:
-	// Constructor
-	AssimpStream() {}
-
-	// Destructor
-	~AssimpStream() {}
-	// Write something using your own functionality
-	void write(const char *message) {
-		print_verbose(String("Open Asset Import: ") + String(message).strip_edges());
-	}
-};
-
-class EditorSceneImporterAssimp : public EditorSceneImporter {
-private:
-	GDCLASS(EditorSceneImporterAssimp, EditorSceneImporter);
-
-	struct AssetImportAnimation {
-		enum Interpolation {
-			INTERP_LINEAR,
-			INTERP_STEP,
-			INTERP_CATMULLROMSPLINE,
-			INTERP_CUBIC_SPLINE
-		};
-	};
-
-	struct BoneInfo {
-		uint32_t bone;
-		float weight;
-	};
-
-	Ref<Mesh> _generate_mesh_from_surface_indices(ImportState &state, const Vector<int> &p_surface_indices,
-			const aiNode *assimp_node, Ref<Skin> &skin,
-			Skeleton3D *&skeleton_assigned);
-
-	// simple object creation functions
-	Node3D *create_light(ImportState &state,
-			const String &node_name,
-			Transform &look_at_transform);
-	Node3D *create_camera(
-			ImportState &state,
-			const String &node_name,
-			Transform &look_at_transform);
-	// non recursive - linear so must not use recursive arguments
-	MeshInstance3D *create_mesh(ImportState &state, const aiNode *assimp_node, const String &node_name, Node *active_node, Transform node_transform);
-	// recursive node generator
-	void _generate_node(ImportState &state, const aiNode *assimp_node);
-	void _insert_animation_track(ImportState &scene, const aiAnimation *assimp_anim, int track_id,
-			int anim_fps, Ref<Animation> animation, float ticks_per_second,
-			Skeleton3D *skeleton, const NodePath &node_path,
-			const String &node_name, aiBone *track_bone);
-
-	void _import_animation(ImportState &state, int p_animation_index, int p_bake_fps);
-	Node *get_node_by_name(ImportState &state, String name);
-	aiBone *get_bone_from_stack(ImportState &state, aiString name);
-	Node3D *_generate_scene(const String &p_path, aiScene *scene, const uint32_t p_flags, int p_bake_fps, const int32_t p_max_bone_weights);
-
-	template <class T>
-	T _interpolate_track(const Vector<float> &p_times, const Vector<T> &p_values, float p_time, AssetImportAnimation::Interpolation p_interp);
-	void _register_project_setting_import(const String generic, const String import_setting_string, const Vector<String> &exts, List<String> *r_extensions, const bool p_enabled) const;
-
-	struct ImportFormat {
-		Vector<String> extensions;
-		bool is_default;
-	};
-
-protected:
-	static void _bind_methods();
-
-public:
-	EditorSceneImporterAssimp() {
-		Assimp::DefaultLogger::create("", Assimp::Logger::VERBOSE);
-		unsigned int severity = Assimp::Logger::Info | Assimp::Logger::Err | Assimp::Logger::Warn;
-		Assimp::DefaultLogger::get()->attachStream(new AssimpStream(), severity);
-	}
-	~EditorSceneImporterAssimp() {
-		Assimp::DefaultLogger::kill();
-	}
-
-	virtual void get_extensions(List<String> *r_extensions) const override;
-	virtual uint32_t get_import_flags() const override;
-	virtual Node *import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr) override;
-	Ref<Image> load_image(ImportState &state, const aiScene *p_scene, String p_path);
-
-	static void RegenerateBoneStack(ImportState &state);
-
-	void RegenerateBoneStack(ImportState &state, aiMesh *mesh);
-};
-#endif
-#endif

+ 0 - 262
modules/assimp/godot_update_assimp.sh

@@ -1,262 +0,0 @@
-rm -rf ../../thirdparty/assimp
-cd ../../thirdparty/
-git clone https://github.com/assimp/assimp.git
-cd assimp
-rm -rf code/3DSExporter.h
-rm -rf code/3DSLoader.h
-rm -rf code/3MFXmlTags.h
-rm -rf code/ABCImporter.h
-rm -rf code/ACLoader.h
-rm -rf code/AMFImporter_Macro.hpp
-rm -rf code/ASELoader.h
-rm -rf code/assbin_chunks.h
-rm -rf code/AssbinExporter.h
-rm -rf code/AssbinLoader.h
-rm -rf code/AssimpCExport.cpp
-rm -rf code/AssxmlExporter.h
-rm -rf code/B3DImporter.h
-# rm -rf code/BaseProcess.cpp
-# rm -rf code/BaseProcess.h
-# rm -rf code/Bitmap.cpp
-rm -rf code/BlenderBMesh.cpp
-rm -rf code/BlenderBMesh.h
-rm -rf code/BlenderCustomData.cpp
-rm -rf code/BlenderCustomData.h
-rm -rf code/BlenderIntermediate.h
-rm -rf code/BlenderLoader.h
-rm -rf code/BlenderModifier.h
-rm -rf code/BlenderSceneGen.h
-rm -rf code/BlenderTessellator.h
-rm -rf code/BVHLoader.h
-rm -rf code/C4DImporter.h
-# rm -rf code/CalcTangentsProcess.h
-# rm -rf code/CInterfaceIOWrapper.cpp
-# rm -rf code/CInterfaceIOWrapper.h
-rm -rf code/COBLoader.h
-rm -rf code/COBScene.h
-rm -rf code/ColladaExporter.h
-rm -rf code/ColladaLoader.h
-# rm -rf code/ComputeUVMappingProcess.h
-# rm -rf code/ConvertToLHProcess.h
-# rm -rf code/CreateAnimMesh.cpp
-rm -rf code/CSMLoader.h
-rm -rf code/D3MFExporter.h
-rm -rf code/D3MFImporter.h
-rm -rf code/D3MFOpcPackage.h
-# rm -rf code/DeboneProcess.h
-# rm -rf code/DefaultIOStream.cpp
-# rm -rf code/DefaultIOSystem.cpp
-# rm -rf code/DefaultProgressHandler.h
-# rm -rf code/DropFaceNormalsProcess.cpp
-# rm -rf code/DropFaceNormalsProcess.h
-rm -rf code/DXFHelper.h
-rm -rf code/DXFLoader.h
-# rm -rf code/EmbedTexturesProcess.cpp
-# rm -rf code/EmbedTexturesProcess.h
-# rm -rf code/FBXCommon.h
-# rm -rf code/FBXCompileConfig.h
-# rm -rf code/FBXDeformer.cpp
-# rm -rf code/FBXDocumentUtil.cpp
-# rm -rf code/FBXDocumentUtil.h
-# rm -rf code/FBXExporter.h
-# rm -rf code/FBXExportNode.h
-# rm -rf code/FBXExportProperty.h
-# rm -rf code/FBXImporter.cpp
-# rm -rf code/FBXImporter.h
-# rm -rf code/FBXImportSettings.h
-# rm -rf code/FBXMeshGeometry.h
-# rm -rf code/FBXModel.cpp
-# rm -rf code/FBXNodeAttribute.cpp
-# rm -rf code/FBXParser.h
-# rm -rf code/FBXProperties.cpp
-# rm -rf code/FBXProperties.h
-# rm -rf code/FBXTokenizer.cpp
-# rm -rf code/FBXTokenizer.h
-# rm -rf code/FBXUtil.cpp
-# rm -rf code/FBXUtil.h
-# rm -rf code/FileLogStream.h
-# rm -rf code/FindDegenerates.h
-# rm -rf code/FindInstancesProcess.h
-# rm -rf code/FindInvalidDataProcess.h
-rm -rf code/FIReader.hpp
-# rm -rf code/FixNormalsStep.cpp
-# rm -rf code/FixNormalsStep.h
-# rm -rf code/GenFaceNormalsProcess.cpp
-# rm -rf code/GenFaceNormalsProcess.h
-# rm -rf code/GenVertexNormalsProcess.cpp
-# rm -rf code/GenVertexNormalsProcess.h
-rm -rf code/glTF2Asset.h
-rm -rf code/glTF2Asset.inl
-rm -rf code/glTF2AssetWriter.inl
-rm -rf code/glTF2Exporter.cpp
-rm -rf code/glTF2Importer.cpp
-rm -rf code/glTF2AssetWriter.h
-rm -rf code/glTFAsset.h
-rm -rf code/glTFAsset.inl
-rm -rf code/glTFAssetWriter.inl
-rm -rf code/glTFExporter.cpp
-rm -rf code/glTFImporter.cpp
-rm -rf code/glTF2Exporter.h
-rm -rf code/glTF2Importer.h
-rm -rf code/glTFAssetWriter.h
-rm -rf code/glTFExporter.h
-rm -rf code/glTFImporter.h
-rm -rf code/HalfLifeFileData.h
-rm -rf code/HMPFileData.h
-rm -rf code/HMPLoader.h
-rm -rf code/HMPLoader.cpp
-rm -rf code/IFF.h
-# rm -rf code/Importer.h
-# rm -rf code/ImproveCacheLocality.h
-rm -rf code/IRRLoader.h
-rm -rf code/IRRMeshLoader.h
-rm -rf code/IRRShared.h
-# rm -rf code/JoinVerticesProcess.h
-# rm -rf code/LimitBoneWeightsProcess.cpp
-# rm -rf code/LimitBoneWeightsProcess.h
-rm -rf code/LWSLoader.h
-rm -rf code/makefile.mingw
-# rm -rf code/MakeVerboseFormat.cpp
-# rm -rf code/MakeVerboseFormat.h
-# rm -rf code/MaterialSystem.h
-rm -rf code/MD2FileData.h
-rm -rf code/MD2Loader.h
-rm -rf code/MD2NormalTable.h
-rm -rf code/MD3FileData.h
-rm -rf code/MD3Loader.h
-rm -rf code/MD4FileData.h
-rm -rf code/MD5Loader.h
-rm -rf code/MD5Parser.cpp
-rm -rf code/MDCFileData.h
-rm -rf code/MDCLoader.h
-rm -rf code/MDLDefaultColorMap.h
-# rm -rf code/MMDCpp14.h
-# rm -rf code/MMDImporter.h
-rm -rf code/MS3DLoader.h
-rm -rf code/NDOLoader.h
-rm -rf code/NFFLoader.h
-rm -rf code/ObjExporter.h
-rm -rf code/ObjFileImporter.h
-rm -rf code/ObjFileMtlImporter.h
-rm -rf code/ObjFileParser.h
-rm -rf code/ObjTools.h
-rm -rf code/ObjExporter.cpp
-rm -rf code/ObjFileImporter.cpp
-rm -rf code/ObjFileMtlImporter.cpp
-rm -rf code/ObjFileParser.cpp
-rm -rf code/OFFLoader.h
-rm -rf code/OFFLoader.cpp
-rm -rf code/OgreImporter.cpp
-rm -rf code/OgreImporter.h
-rm -rf code/OgreParsingUtils.h
-rm -rf code/OgreXmlSerializer.h
-rm -rf code/OgreXmlSerializer.cpp
-rm -rf code/OgreBinarySerializer.cpp
-rm -rf code/OpenGEXExporter.cpp
-rm -rf code/OpenGEXExporter.h
-rm -rf code/OpenGEXImporter.h
-rm -rf code/OpenGEXStructs.h
-rm -rf code/OpenGEXImporter.cpp
-# rm -rf code/OptimizeGraph.h
-# rm -rf code/OptimizeMeshes.cpp
-# rm -rf code/OptimizeMeshes.h
-rm -rf code/PlyExporter.h
-rm -rf code/PlyLoader.h
-# rm -rf code/PolyTools.h
-# rm -rf code/PostStepRegistry.cpp
-# rm -rf code/PretransformVertices.h
-rm -rf code/Q3BSPFileData.h
-rm -rf code/Q3BSPFileImporter.h
-rm -rf code/Q3BSPFileParser.cpp
-rm -rf code/Q3BSPFileParser.h
-rm -rf code/Q3BSPZipArchive.cpp
-rm -rf code/Q3BSPZipArchive.h
-rm -rf code/Q3DLoader.h
-rm -rf code/Q3DLoader.cpp
-rm -rf code/Q3BSPFileImporter.cpp
-rm -rf code/RawLoader.h
-# rm -rf code/RemoveComments.cpp
-# rm -rf code/RemoveRedundantMaterials.cpp
-# rm -rf code/RemoveRedundantMaterials.h
-# rm -rf code/RemoveVCProcess.h
-# rm -rf code/ScaleProcess.cpp
-# rm -rf code/ScaleProcess.h
-# rm -rf code/scene.cpp
-# rm -rf code/ScenePreprocessor.cpp
-# rm -rf code/ScenePreprocessor.h
-# rm -rf code/ScenePrivate.h
-# rm -rf code/SGSpatialSort.cpp
-rm -rf code/SIBImporter.h
-rm -rf code/SMDLoader.cpp
-# rm -rf code/simd.cpp
-# rm -rf code/simd.h
-# rm -rf code/SortByPTypeProcess.h
-# rm -rf code/SplitByBoneCountProcess.h
-# rm -rf code/SplitLargeMeshes.h
-# rm -rf code/StdOStreamLogStream.h
-rm -rf code/StepExporter.h
-rm -rf code/StepExporter.cpp
-rm -rf code/STLExporter.cpp
-rm -rf code/STLExporter.h
-rm -rf code/STLLoader.h
-rm -rf code/STLLoader.cpp
-# rm -rf code/TargetAnimation.cpp
-# rm -rf code/TargetAnimation.h
-rm -rf code/TerragenLoader.h
-rm -rf code/TerragenLoader.cpp
-# rm -rf code/TextureTransform.h
-# rm -rf code/TriangulateProcess.h
-rm -rf code/UnrealLoader.h
-# rm -rf code/ValidateDataStructure.h
-# rm -rf code/Version.cpp
-# rm -rf code/VertexTriangleAdjacency.cpp
-# rm -rf code/VertexTriangleAdjacency.h
-# rm -rf code/Win32DebugLogStream.h
-rm -rf code/X3DImporter_Macro.hpp
-rm -rf code/X3DImporter_Metadata.cpp
-rm -rf code/X3DImporter_Networking.cpp
-rm -rf code/X3DImporter_Texturing.cpp
-rm -rf code/X3DImporter_Shape.cpp
-rm -rf code/X3DImporter_Rendering.cpp
-rm -rf code/X3DImporter_Postprocess.cpp
-rm -rf code/X3DImporter_Light.cpp
-rm -rf code/X3DImporter_Group.cpp
-rm -rf code/X3DImporter_Geometry3D.cpp
-rm -rf code/X3DImporter_Geometry2D.cpp
-rm -rf code/X3DImporter.cpp
-rm -rf code/X3DExporter.cpp
-rm -rf code/X3DVocabulary.cpp
-rm -rf code/XFileExporter.h
-rm -rf code/XFileExporter.cpp
-rm -rf code/XFileHelper.h
-rm -rf code/XFileHelper.cpp
-rm -rf code/XFileImporter.h
-rm -rf code/XFileImporter.cpp
-rm -rf code/XFileParser.h
-rm -rf code/XFileParser.cpp
-rm -rf code/XGLLoader.h
-rm -rf code/XGLLoader.cpp
-rm -rf code/Importer
-rm -rf .git
-rm -rf cmake-modules
-rm -rf doc
-rm -rf packaging
-rm -rf port
-rm -rf samples
-rm -rf scripts
-rm -rf test
-rm -rf tools
-rm -rf contrib/zlib
-rm -rf contrib/android-cmake
-rm -rf contrib/gtest
-rm -rf contrib/clipper
-rm -rf contrib/irrXML
-rm -rf contrib/Open3DGC
-rm -rf contrib/openddlparser
-rm -rf contrib/poly2tri
-#rm -rf contrib/rapidjson
-rm -rf contrib/unzip
-rm -rf contrib/zip
-rm -rf contrib/stb_image
-rm .travis*
-

+ 0 - 132
modules/assimp/import_state.h

@@ -1,132 +0,0 @@
-/*************************************************************************/
-/*  import_state.h                                                       */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the       */
-/* "Software"), to deal in the Software without restriction, including   */
-/* without limitation the rights to use, copy, modify, merge, publish,   */
-/* distribute, sublicense, and/or sell copies of the Software, and to    */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions:                                             */
-/*                                                                       */
-/* The above copyright notice and this permission notice shall be        */
-/* included in all copies or substantial portions of the Software.       */
-/*                                                                       */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
-/*************************************************************************/
-
-#ifndef EDITOR_SCENE_IMPORT_STATE_H
-#define EDITOR_SCENE_IMPORT_STATE_H
-
-#include "core/core_bind.h"
-#include "core/io/resource_importer.h"
-#include "core/templates/vector.h"
-#include "editor/import/resource_importer_scene.h"
-#include "editor/project_settings_editor.h"
-#include "scene/3d/mesh_instance_3d.h"
-#include "scene/3d/node_3d.h"
-#include "scene/3d/skeleton_3d.h"
-#include "scene/animation/animation_player.h"
-#include "scene/resources/animation.h"
-#include "scene/resources/surface_tool.h"
-
-#include <assimp/matrix4x4.h>
-#include <assimp/scene.h>
-#include <assimp/types.h>
-#include <assimp/DefaultLogger.hpp>
-#include <assimp/LogStream.hpp>
-#include <assimp/Logger.hpp>
-
-namespace AssimpImporter {
-/** Import state is for global scene import data
- * This makes the code simpler and contains useful lookups.
- */
-struct ImportState {
-	String path;
-	Node3D *root;
-	const aiScene *assimp_scene;
-	uint32_t max_bone_weights;
-
-	Map<String, Ref<Mesh>> mesh_cache;
-	Map<int, Ref<Material>> material_cache;
-	Map<String, int> light_cache;
-	Map<String, int> camera_cache;
-
-	// very useful for when you need to ask assimp for the bone mesh
-
-	Map<const aiNode *, Node *> assimp_node_map;
-	Map<String, Ref<Image>> path_to_image_cache;
-
-	// Generation 3 - determinisitic iteration
-	// to lower potential recursion errors
-	List<const aiNode *> nodes;
-	Map<const aiNode *, Node3D *> flat_node_map;
-	AnimationPlayer *animation_player;
-
-	// Generation 3 - deterministic armatures
-	// list of armature nodes - flat and simple to parse
-	// assimp node, node in godot
-	List<aiNode *> armature_nodes;
-	Map<const aiNode *, Skeleton3D *> armature_skeletons;
-	Map<aiBone *, Skeleton3D *> skeleton_bone_map;
-	// Generation 3 - deterministic bone handling
-	// bones from the stack are popped when found
-	// this means we can detect
-	// what bones are for other armatures
-	List<aiBone *> bone_stack;
-
-	// EditorSceneImporter::ImportFlags
-	uint32_t import_flags;
-};
-
-struct AssimpImageData {
-	Ref<Image> raw_image;
-	Ref<ImageTexture> texture;
-	aiTextureMapMode map_mode[2];
-};
-
-/** Recursive state is used to push state into functions instead of specifying them
-	* This makes the code easier to handle too and add extra arguments without breaking things
-	*/
-struct RecursiveState {
-	RecursiveState() {} // do not construct :)
-	RecursiveState(
-			Transform &_node_transform,
-			Skeleton3D *_skeleton,
-			Node3D *_new_node,
-			String &_node_name,
-			aiNode *_assimp_node,
-			Node *_parent_node,
-			aiBone *_bone) :
-			node_transform(_node_transform),
-			skeleton(_skeleton),
-			new_node(_new_node),
-			node_name(_node_name),
-			assimp_node(_assimp_node),
-			parent_node(_parent_node),
-			bone(_bone) {}
-
-	Transform node_transform;
-	Skeleton3D *skeleton = nullptr;
-	Node3D *new_node = nullptr;
-	String node_name;
-	aiNode *assimp_node = nullptr;
-	Node *parent_node = nullptr;
-	aiBone *bone = nullptr;
-};
-} // namespace AssimpImporter
-
-#endif // EDITOR_SCENE_IMPORT_STATE_H

+ 0 - 463
modules/assimp/import_utils.h

@@ -1,463 +0,0 @@
-/*************************************************************************/
-/*  import_utils.h                                                       */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the       */
-/* "Software"), to deal in the Software without restriction, including   */
-/* without limitation the rights to use, copy, modify, merge, publish,   */
-/* distribute, sublicense, and/or sell copies of the Software, and to    */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions:                                             */
-/*                                                                       */
-/* The above copyright notice and this permission notice shall be        */
-/* included in all copies or substantial portions of the Software.       */
-/*                                                                       */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
-/*************************************************************************/
-
-#ifndef IMPORT_UTILS_IMPORTER_ASSIMP_H
-#define IMPORT_UTILS_IMPORTER_ASSIMP_H
-
-#include "core/io/image_loader.h"
-#include "import_state.h"
-
-#include <assimp/SceneCombiner.h>
-#include <assimp/cexport.h>
-#include <assimp/cimport.h>
-#include <assimp/matrix4x4.h>
-#include <assimp/pbrmaterial.h>
-#include <assimp/postprocess.h>
-#include <assimp/scene.h>
-#include <assimp/DefaultLogger.hpp>
-#include <assimp/Importer.hpp>
-#include <assimp/LogStream.hpp>
-#include <assimp/Logger.hpp>
-#include <string>
-
-using namespace AssimpImporter;
-
-#define AI_PROPERTIES aiTextureType_UNKNOWN, 0
-#define AI_NULL 0, 0
-#define AI_MATKEY_FBX_MAYA_BASE_COLOR_FACTOR "$raw.Maya|baseColor"
-#define AI_MATKEY_FBX_MAYA_METALNESS_FACTOR "$raw.Maya|metalness"
-#define AI_MATKEY_FBX_MAYA_DIFFUSE_ROUGHNESS_FACTOR "$raw.Maya|diffuseRoughness"
-
-#define AI_MATKEY_FBX_MAYA_EMISSION_TEXTURE "$raw.Maya|emissionColor|file"
-#define AI_MATKEY_FBX_MAYA_EMISSIVE_FACTOR "$raw.Maya|emission"
-#define AI_MATKEY_FBX_MAYA_METALNESS_TEXTURE "$raw.Maya|metalness|file"
-#define AI_MATKEY_FBX_MAYA_METALNESS_UV_XFORM "$raw.Maya|metalness|uvtrafo"
-#define AI_MATKEY_FBX_MAYA_DIFFUSE_ROUGHNESS_TEXTURE "$raw.Maya|diffuseRoughness|file"
-#define AI_MATKEY_FBX_MAYA_DIFFUSE_ROUGHNESS_UV_XFORM "$raw.Maya|diffuseRoughness|uvtrafo"
-#define AI_MATKEY_FBX_MAYA_BASE_COLOR_TEXTURE "$raw.Maya|baseColor|file"
-#define AI_MATKEY_FBX_MAYA_BASE_COLOR_UV_XFORM "$raw.Maya|baseColor|uvtrafo"
-#define AI_MATKEY_FBX_MAYA_NORMAL_TEXTURE "$raw.Maya|normalCamera|file"
-#define AI_MATKEY_FBX_MAYA_NORMAL_UV_XFORM "$raw.Maya|normalCamera|uvtrafo"
-
-#define AI_MATKEY_FBX_NORMAL_TEXTURE "$raw.Maya|normalCamera|file"
-#define AI_MATKEY_FBX_NORMAL_UV_XFORM "$raw.Maya|normalCamera|uvtrafo"
-
-#define AI_MATKEY_FBX_MAYA_STINGRAY_DISPLACEMENT_SCALING_FACTOR "$raw.Maya|displacementscaling"
-#define AI_MATKEY_FBX_MAYA_STINGRAY_BASE_COLOR_FACTOR "$raw.Maya|base_color"
-#define AI_MATKEY_FBX_MAYA_STINGRAY_EMISSIVE_FACTOR "$raw.Maya|emissive"
-#define AI_MATKEY_FBX_MAYA_STINGRAY_METALLIC_FACTOR "$raw.Maya|metallic"
-#define AI_MATKEY_FBX_MAYA_STINGRAY_ROUGHNESS_FACTOR "$raw.Maya|roughness"
-#define AI_MATKEY_FBX_MAYA_STINGRAY_EMISSIVE_INTENSITY_FACTOR "$raw.Maya|emissive_intensity"
-
-#define AI_MATKEY_FBX_MAYA_STINGRAY_NORMAL_TEXTURE "$raw.Maya|TEX_normal_map|file"
-#define AI_MATKEY_FBX_MAYA_STINGRAY_NORMAL_UV_XFORM "$raw.Maya|TEX_normal_map|uvtrafo"
-#define AI_MATKEY_FBX_MAYA_STINGRAY_COLOR_TEXTURE "$raw.Maya|TEX_color_map|file"
-#define AI_MATKEY_FBX_MAYA_STINGRAY_COLOR_UV_XFORM "$raw.Maya|TEX_color_map|uvtrafo"
-#define AI_MATKEY_FBX_MAYA_STINGRAY_METALLIC_TEXTURE "$raw.Maya|TEX_metallic_map|file"
-#define AI_MATKEY_FBX_MAYA_STINGRAY_METALLIC_UV_XFORM "$raw.Maya|TEX_metallic_map|uvtrafo"
-#define AI_MATKEY_FBX_MAYA_STINGRAY_ROUGHNESS_TEXTURE "$raw.Maya|TEX_roughness_map|file"
-#define AI_MATKEY_FBX_MAYA_STINGRAY_ROUGHNESS_UV_XFORM "$raw.Maya|TEX_roughness_map|uvtrafo"
-#define AI_MATKEY_FBX_MAYA_STINGRAY_EMISSIVE_TEXTURE "$raw.Maya|TEX_emissive_map|file"
-#define AI_MATKEY_FBX_MAYA_STINGRAY_EMISSIVE_UV_XFORM "$raw.Maya|TEX_emissive_map|uvtrafo"
-#define AI_MATKEY_FBX_MAYA_STINGRAY_AO_TEXTURE "$raw.Maya|TEX_ao_map|file"
-#define AI_MATKEY_FBX_MAYA_STINGRAY_AO_UV_XFORM "$raw.Maya|TEX_ao_map|uvtrafo"
-
-/**
- * Assimp Utils
- * Conversion tools / glue code to convert from assimp to godot
-*/
-class AssimpUtils {
-public:
-	/**
-	 * calculate tangents for mesh data from assimp data
-	 */
-	static void calc_tangent_from_mesh(const aiMesh *ai_mesh, int i, int tri_index, int index, Color *w) {
-		const aiVector3D normals = ai_mesh->mAnimMeshes[i]->mNormals[tri_index];
-		const Vector3 godot_normal = Vector3(normals.x, normals.y, normals.z);
-		const aiVector3D tangent = ai_mesh->mAnimMeshes[i]->mTangents[tri_index];
-		const Vector3 godot_tangent = Vector3(tangent.x, tangent.y, tangent.z);
-		const aiVector3D bitangent = ai_mesh->mAnimMeshes[i]->mBitangents[tri_index];
-		const Vector3 godot_bitangent = Vector3(bitangent.x, bitangent.y, bitangent.z);
-		float d = godot_normal.cross(godot_tangent).dot(godot_bitangent) > 0.0f ? 1.0f : -1.0f;
-		Color plane_tangent = Color(tangent.x, tangent.y, tangent.z, d);
-		w[index] = plane_tangent;
-	}
-
-	struct AssetImportFbx {
-		enum ETimeMode {
-			TIME_MODE_DEFAULT = 0,
-			TIME_MODE_120 = 1,
-			TIME_MODE_100 = 2,
-			TIME_MODE_60 = 3,
-			TIME_MODE_50 = 4,
-			TIME_MODE_48 = 5,
-			TIME_MODE_30 = 6,
-			TIME_MODE_30_DROP = 7,
-			TIME_MODE_NTSC_DROP_FRAME = 8,
-			TIME_MODE_NTSC_FULL_FRAME = 9,
-			TIME_MODE_PAL = 10,
-			TIME_MODE_CINEMA = 11,
-			TIME_MODE_1000 = 12,
-			TIME_MODE_CINEMA_ND = 13,
-			TIME_MODE_CUSTOM = 14,
-			TIME_MODE_TIME_MODE_COUNT = 15
-		};
-		enum UpAxis {
-			UP_VECTOR_AXIS_X = 1,
-			UP_VECTOR_AXIS_Y = 2,
-			UP_VECTOR_AXIS_Z = 3
-		};
-		enum FrontAxis {
-			FRONT_PARITY_EVEN = 1,
-			FRONT_PARITY_ODD = 2,
-		};
-
-		enum CoordAxis {
-			COORD_RIGHT = 0,
-			COORD_LEFT = 1
-		};
-	};
-
-	/** Get assimp string
-    * automatically filters the string data
-    */
-	static String get_assimp_string(const aiString &p_string) {
-		//convert an assimp String to a Godot String
-		String name;
-		name.parse_utf8(p_string.C_Str() /*,p_string.length*/);
-		if (name.find(":") != -1) {
-			String replaced_name = name.split(":")[1];
-			print_verbose("Replacing " + name + " containing : with " + replaced_name);
-			name = replaced_name;
-		}
-
-		return name;
-	}
-
-	static String get_anim_string_from_assimp(const aiString &p_string) {
-		String name;
-		name.parse_utf8(p_string.C_Str() /*,p_string.length*/);
-		if (name.find(":") != -1) {
-			String replaced_name = name.split(":")[1];
-			print_verbose("Replacing " + name + " containing : with " + replaced_name);
-			name = replaced_name;
-		}
-		return name;
-	}
-
-	/**
-     * No filter logic get_raw_string_from_assimp
-     * This just convers the aiString to a parsed utf8 string
-     * Without removing special chars etc
-     */
-	static String get_raw_string_from_assimp(const aiString &p_string) {
-		String name;
-		name.parse_utf8(p_string.C_Str() /*,p_string.length*/);
-		return name;
-	}
-
-	static Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps) {
-		return Ref<Animation>();
-	}
-
-	/**
-     * Converts aiMatrix4x4 to godot Transform
-    */
-	static const Transform assimp_matrix_transform(const aiMatrix4x4 p_matrix) {
-		aiMatrix4x4 matrix = p_matrix;
-		Transform xform;
-		xform.set(matrix.a1, matrix.a2, matrix.a3, matrix.b1, matrix.b2, matrix.b3, matrix.c1, matrix.c2, matrix.c3, matrix.a4, matrix.b4, matrix.c4);
-		return xform;
-	}
-
-	/** Get fbx fps for time mode meta data
-     */
-	static float get_fbx_fps(int32_t time_mode, const aiScene *p_scene) {
-		switch (time_mode) {
-			case AssetImportFbx::TIME_MODE_DEFAULT:
-				return 24; //hack
-			case AssetImportFbx::TIME_MODE_120:
-				return 120;
-			case AssetImportFbx::TIME_MODE_100:
-				return 100;
-			case AssetImportFbx::TIME_MODE_60:
-				return 60;
-			case AssetImportFbx::TIME_MODE_50:
-				return 50;
-			case AssetImportFbx::TIME_MODE_48:
-				return 48;
-			case AssetImportFbx::TIME_MODE_30:
-				return 30;
-			case AssetImportFbx::TIME_MODE_30_DROP:
-				return 30;
-			case AssetImportFbx::TIME_MODE_NTSC_DROP_FRAME:
-				return 29.9700262f;
-			case AssetImportFbx::TIME_MODE_NTSC_FULL_FRAME:
-				return 29.9700262f;
-			case AssetImportFbx::TIME_MODE_PAL:
-				return 25;
-			case AssetImportFbx::TIME_MODE_CINEMA:
-				return 24;
-			case AssetImportFbx::TIME_MODE_1000:
-				return 1000;
-			case AssetImportFbx::TIME_MODE_CINEMA_ND:
-				return 23.976f;
-			case AssetImportFbx::TIME_MODE_CUSTOM:
-				int32_t frame_rate = -1;
-				p_scene->mMetaData->Get("FrameRate", frame_rate);
-				return frame_rate;
-		}
-		return 0;
-	}
-
-	/**
-      * Get global transform for the current node - so we can use world space rather than
-      * local space coordinates
-      * useful if you need global - although recommend using local wherever possible over global
-      * as you could break fbx scaling :)
-      */
-	static Transform _get_global_assimp_node_transform(const aiNode *p_current_node) {
-		aiNode const *current_node = p_current_node;
-		Transform xform;
-		while (current_node != nullptr) {
-			xform = assimp_matrix_transform(current_node->mTransformation) * xform;
-			current_node = current_node->mParent;
-		}
-		return xform;
-	}
-
-	/**
-	  * Find hardcoded textures from assimp which could be in many different directories
-	  */
-	static void find_texture_path(const String &p_path, _Directory &dir, String &path, bool &found, String extension) {
-		Vector<String> paths;
-		paths.push_back(path.get_basename() + extension);
-		paths.push_back(path + extension);
-		paths.push_back(path);
-		paths.push_back(p_path.get_base_dir().plus_file(path.get_file().get_basename() + extension));
-		paths.push_back(p_path.get_base_dir().plus_file(path.get_file() + extension));
-		paths.push_back(p_path.get_base_dir().plus_file(path.get_file()));
-		paths.push_back(p_path.get_base_dir().plus_file("textures/" + path.get_file().get_basename() + extension));
-		paths.push_back(p_path.get_base_dir().plus_file("textures/" + path.get_file() + extension));
-		paths.push_back(p_path.get_base_dir().plus_file("textures/" + path.get_file()));
-		paths.push_back(p_path.get_base_dir().plus_file("Textures/" + path.get_file().get_basename() + extension));
-		paths.push_back(p_path.get_base_dir().plus_file("Textures/" + path.get_file() + extension));
-		paths.push_back(p_path.get_base_dir().plus_file("Textures/" + path.get_file()));
-		paths.push_back(p_path.get_base_dir().plus_file("../Textures/" + path.get_file() + extension));
-		paths.push_back(p_path.get_base_dir().plus_file("../Textures/" + path.get_file().get_basename() + extension));
-		paths.push_back(p_path.get_base_dir().plus_file("../Textures/" + path.get_file()));
-		paths.push_back(p_path.get_base_dir().plus_file("../textures/" + path.get_file().get_basename() + extension));
-		paths.push_back(p_path.get_base_dir().plus_file("../textures/" + path.get_file() + extension));
-		paths.push_back(p_path.get_base_dir().plus_file("../textures/" + path.get_file()));
-		paths.push_back(p_path.get_base_dir().plus_file("texture/" + path.get_file().get_basename() + extension));
-		paths.push_back(p_path.get_base_dir().plus_file("texture/" + path.get_file() + extension));
-		paths.push_back(p_path.get_base_dir().plus_file("texture/" + path.get_file()));
-		paths.push_back(p_path.get_base_dir().plus_file("Texture/" + path.get_file().get_basename() + extension));
-		paths.push_back(p_path.get_base_dir().plus_file("Texture/" + path.get_file() + extension));
-		paths.push_back(p_path.get_base_dir().plus_file("Texture/" + path.get_file()));
-		paths.push_back(p_path.get_base_dir().plus_file("../Texture/" + path.get_file() + extension));
-		paths.push_back(p_path.get_base_dir().plus_file("../Texture/" + path.get_file().get_basename() + extension));
-		paths.push_back(p_path.get_base_dir().plus_file("../Texture/" + path.get_file()));
-		paths.push_back(p_path.get_base_dir().plus_file("../texture/" + path.get_file().get_basename() + extension));
-		paths.push_back(p_path.get_base_dir().plus_file("../texture/" + path.get_file() + extension));
-		paths.push_back(p_path.get_base_dir().plus_file("../texture/" + path.get_file()));
-		for (int i = 0; i < paths.size(); i++) {
-			if (dir.file_exists(paths[i])) {
-				found = true;
-				path = paths[i];
-				return;
-			}
-		}
-	}
-
-	/** find the texture path for the supplied fbx path inside godot
-      * very simple lookup for subfolders etc for a texture which may or may not be in a directory
-      */
-	static void find_texture_path(const String &r_p_path, String &r_path, bool &r_found) {
-		_Directory dir;
-
-		List<String> exts;
-		ImageLoader::get_recognized_extensions(&exts);
-
-		Vector<String> split_path = r_path.get_basename().split("*");
-		if (split_path.size() == 2) {
-			r_found = true;
-			return;
-		}
-
-		if (dir.file_exists(r_p_path.get_base_dir() + r_path.get_file())) {
-			r_path = r_p_path.get_base_dir() + r_path.get_file();
-			r_found = true;
-			return;
-		}
-
-		for (int32_t i = 0; i < exts.size(); i++) {
-			if (r_found) {
-				return;
-			}
-			find_texture_path(r_p_path, dir, r_path, r_found, "." + exts[i]);
-		}
-	}
-
-	/**
-	  * set_texture_mapping_mode
-	  * Helper to check the mapping mode of the texture (repeat, clamp and mirror)
-	  */
-	static void set_texture_mapping_mode(aiTextureMapMode *map_mode, Ref<ImageTexture> texture) {
-		ERR_FAIL_COND(texture.is_null());
-		ERR_FAIL_COND(map_mode == nullptr);
-		// FIXME: Commented out during Vulkan port.
-		/*
-		aiTextureMapMode tex_mode = map_mode[0];
-
-		int32_t flags = Texture2D::FLAGS_DEFAULT;
-		if (tex_mode == aiTextureMapMode_Wrap) {
-			//Default
-		} else if (tex_mode == aiTextureMapMode_Clamp) {
-			flags = flags & ~Texture2D::FLAG_REPEAT;
-		} else if (tex_mode == aiTextureMapMode_Mirror) {
-			flags = flags | Texture2D::FLAG_MIRRORED_REPEAT;
-		}
-		texture->set_flags(flags);
-		*/
-	}
-
-	/**
-	  * Load or load from cache image :)
-	  */
-	static Ref<Image> load_image(ImportState &state, const aiScene *p_scene, String p_path) {
-		Map<String, Ref<Image>>::Element *match = state.path_to_image_cache.find(p_path);
-
-		// if our cache contains this image then don't bother
-		if (match) {
-			return match->get();
-		}
-
-		Vector<String> split_path = p_path.get_basename().split("*");
-		if (split_path.size() == 2) {
-			size_t texture_idx = split_path[1].to_int();
-			ERR_FAIL_COND_V(texture_idx >= p_scene->mNumTextures, Ref<Image>());
-			aiTexture *tex = p_scene->mTextures[texture_idx];
-			String filename = AssimpUtils::get_raw_string_from_assimp(tex->mFilename);
-			filename = filename.get_file();
-			print_verbose("Open Asset Import: Loading embedded texture " + filename);
-			if (tex->mHeight == 0) {
-				if (tex->CheckFormat("png")) {
-					ERR_FAIL_COND_V(Image::_png_mem_loader_func == nullptr, Ref<Image>());
-					Ref<Image> img = Image::_png_mem_loader_func((uint8_t *)tex->pcData, tex->mWidth);
-					ERR_FAIL_COND_V(img.is_null(), Ref<Image>());
-					state.path_to_image_cache.insert(p_path, img);
-					return img;
-				} else if (tex->CheckFormat("jpg")) {
-					ERR_FAIL_COND_V(Image::_jpg_mem_loader_func == nullptr, Ref<Image>());
-					Ref<Image> img = Image::_jpg_mem_loader_func((uint8_t *)tex->pcData, tex->mWidth);
-					ERR_FAIL_COND_V(img.is_null(), Ref<Image>());
-					state.path_to_image_cache.insert(p_path, img);
-					return img;
-				} else if (tex->CheckFormat("dds")) {
-					ERR_FAIL_COND_V_MSG(true, Ref<Image>(), "Open Asset Import: Embedded dds not implemented");
-				}
-			} else {
-				Ref<Image> img;
-				img.instance();
-				PackedByteArray arr;
-				uint32_t size = tex->mWidth * tex->mHeight;
-				arr.resize(size);
-				memcpy(arr.ptrw(), tex->pcData, size);
-				ERR_FAIL_COND_V(arr.size() % 4 != 0, Ref<Image>());
-				//ARGB8888 to RGBA8888
-				for (int32_t i = 0; i < arr.size() / 4; i++) {
-					arr.ptrw()[(4 * i) + 3] = arr[(4 * i) + 0];
-					arr.ptrw()[(4 * i) + 0] = arr[(4 * i) + 1];
-					arr.ptrw()[(4 * i) + 1] = arr[(4 * i) + 2];
-					arr.ptrw()[(4 * i) + 2] = arr[(4 * i) + 3];
-				}
-				img->create(tex->mWidth, tex->mHeight, true, Image::FORMAT_RGBA8, arr);
-				ERR_FAIL_COND_V(img.is_null(), Ref<Image>());
-				state.path_to_image_cache.insert(p_path, img);
-				return img;
-			}
-			return Ref<Image>();
-		} else {
-			Ref<Texture2D> texture = ResourceLoader::load(p_path);
-			ERR_FAIL_COND_V(texture.is_null(), Ref<Image>());
-			Ref<Image> image = texture->get_data();
-			ERR_FAIL_COND_V(image.is_null(), Ref<Image>());
-			state.path_to_image_cache.insert(p_path, image);
-			return image;
-		}
-
-		return Ref<Image>();
-	}
-
-	/* create texture from assimp data, if found in path */
-	static bool CreateAssimpTexture(
-			AssimpImporter::ImportState &state,
-			aiString texture_path,
-			String &filename,
-			String &path,
-			AssimpImageData &image_state) {
-		filename = get_raw_string_from_assimp(texture_path);
-		path = state.path.get_base_dir().plus_file(filename.replace("\\", "/"));
-		bool found = false;
-		find_texture_path(state.path, path, found);
-		if (found) {
-			image_state.raw_image = AssimpUtils::load_image(state, state.assimp_scene, path);
-			if (image_state.raw_image.is_valid()) {
-				image_state.texture.instance();
-				image_state.texture->create_from_image(image_state.raw_image);
-				// FIXME: Commented out during Vulkan port.
-				//image_state.texture->set_storage(ImageTexture::STORAGE_COMPRESS_LOSSY);
-				return true;
-			}
-		}
-
-		return false;
-	}
-	/** GetAssimpTexture
-	  * Designed to retrieve textures for you
-	  */
-	static bool GetAssimpTexture(
-			AssimpImporter::ImportState &state,
-			aiMaterial *ai_material,
-			aiTextureType texture_type,
-			String &filename,
-			String &path,
-			AssimpImageData &image_state) {
-		aiString ai_filename = aiString();
-		if (AI_SUCCESS == ai_material->GetTexture(texture_type, 0, &ai_filename, nullptr, nullptr, nullptr, nullptr, image_state.map_mode)) {
-			return CreateAssimpTexture(state, ai_filename, filename, path, image_state);
-		}
-
-		return false;
-	}
-};
-
-#endif // IMPORT_UTILS_IMPORTER_ASSIMP_H

+ 0 - 58
modules/assimp/register_types.cpp

@@ -1,58 +0,0 @@
-/*************************************************************************/
-/*  register_types.cpp                                                   */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the       */
-/* "Software"), to deal in the Software without restriction, including   */
-/* without limitation the rights to use, copy, modify, merge, publish,   */
-/* distribute, sublicense, and/or sell copies of the Software, and to    */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions:                                             */
-/*                                                                       */
-/* The above copyright notice and this permission notice shall be        */
-/* included in all copies or substantial portions of the Software.       */
-/*                                                                       */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
-/*************************************************************************/
-
-#include "register_types.h"
-
-#include "editor/editor_node.h"
-#include "editor_scene_importer_assimp.h"
-
-#ifdef TOOLS_ENABLED
-static void _editor_init() {
-	Ref<EditorSceneImporterAssimp> import_assimp;
-	import_assimp.instance();
-	ResourceImporterScene::get_singleton()->add_importer(import_assimp);
-}
-#endif
-
-void register_assimp_types() {
-#ifdef TOOLS_ENABLED
-	ClassDB::APIType prev_api = ClassDB::get_current_api();
-	ClassDB::set_current_api(ClassDB::API_EDITOR);
-
-	ClassDB::register_class<EditorSceneImporterAssimp>();
-
-	ClassDB::set_current_api(prev_api);
-
-	EditorNode::add_init_callback(_editor_init);
-#endif
-}
-
-void unregister_assimp_types() {
-}

+ 0 - 37
modules/assimp/register_types.h

@@ -1,37 +0,0 @@
-/*************************************************************************/
-/*  register_types.h                                                     */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the       */
-/* "Software"), to deal in the Software without restriction, including   */
-/* without limitation the rights to use, copy, modify, merge, publish,   */
-/* distribute, sublicense, and/or sell copies of the Software, and to    */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions:                                             */
-/*                                                                       */
-/* The above copyright notice and this permission notice shall be        */
-/* included in all copies or substantial portions of the Software.       */
-/*                                                                       */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
-/*************************************************************************/
-
-#ifndef ASSIMP_REGISTER_TYPES_H
-#define ASSIMP_REGISTER_TYPES_H
-
-void register_assimp_types();
-void unregister_assimp_types();
-
-#endif // ASSIMP_REGISTER_TYPES_H

+ 0 - 18
thirdparty/README.md

@@ -6,24 +6,6 @@ readability.
 Subcategories (`###` level) where needed are separated by a single empty line.
 
 
-## assimp
-
-- Upstream: http://github.com/assimp/assimp
-- Version: git (308db73d0b3c2d1870cd3e465eaa283692a4cf23, 2019)
-- License: BSD-3-Clause
-
-Files extracted from upstream source:
-
-- Run `cmake .` in root folder to generate files
-- `code/{CApi,Common,FBX,Material,PostProcessing}/`
-- `contrib/utf8cpp/source/`
-- `include/`
-- `revision.h`
-- `CREDITS` and `LICENSE` files
-- `rm -f code/Common/ZipArchiveIOSystem.cpp include/assimp/ZipArchiveIOSystem.h
-   include/assimp/irrXMLWrapper.h`
-
-
 ## basis_universal
 
 - Upstream: https://github.com/BinomialLLC/basis_universal

+ 0 - 183
thirdparty/assimp/CREDITS

@@ -1,183 +0,0 @@
-===============================================================
-Open Asset Import Library (Assimp)
-Developers and Contributors
-===============================================================
-
-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 (Design).
-
-- Thomas Schulze,
-X-, Collada-, BVH-Loader, Postprocessing framework. Data structure & Interface design, documentation.
-
-- Kim Kulling,
-Obj-, Q3BSD-, OpenGEX-Loader, Logging system, CMake-build-environment, Linux-build, Website ( Admin ), Coverity ( Admin ), Glitter ( Admin ).
-
-- R.Schmidt,
-Linux build, eclipse support.
-
-- Matthias Gubisch,
-Assimp.net
-Visual Studio 9 support, bugfixes.
-
-- Mark Sibly
-B3D-Loader, Assimp testing
-
-- Jonathan Klein
-Ogre Loader, VC2010 fixes and CMake fixes.
-
-- Sebastian Hempel,
-PyAssimp (first version)
-Compile-Bugfixes for mingw, add environment for static library support in make.
-
-- Jonathan Pokrass
-Supplied a bugfix concerning the scaling in the md3 loader.
-
-- Andrew Galante,
-Submitted patches to make Assimp compile with GCC-4, a makefile and the xcode3 workspace.
-
-- Andreas Nagel
-First Assimp testing & verification under Windows Vista 64 Bit.
-
-- Marius Schr�der
-Allowed us to use many of his models for screenshots and testing.
-
-- Christian Schubert
-Supplied various XFiles for testing purposes.
-
-- Tizian Wieland
-Searched the web for hundreds of test models for internal use
-
-- John Connors
-Supplied patches for linux and SCons.
-
-- T. R.
-The GUY who performed some of the CSM mocaps.
-
-- Andy Maloney
-Contributed fixes for the documentation and the doxygen markup
-
-- Zhao Lei
-Contributed several bugfixes fixing memory leaks and improving float parsing 
-
-- sueastside
-Updated PyAssimp to the latest Assimp data structures and provided a script to keep the Python binding up-to-date.
-
-- Tobias Rittig
-Collada testing with Cinema 4D
-
-- Brad Grantham
-Improvements in OpenGL-Sample.
-
-- Robert Ramirez
-Add group loading feature to Obj-Loader.
-
-- Chris Maiwald
-Many bugreports, improving Assimp's portability, regular testing & feedback.
-
-- Stepan Hrbek
-Bugreport and fix for a obj-materialloader crash.
-
-- David Nadlinger
-D bindings, CMake install support.
-
-- Dario Accornero
-Contributed several patches regarding Mac OS/XCode targets, bug reports.
-
-- Martin Walser (Samhayne)
-Contributed the 'SimpleTexturedOpenGl' sample.
-
-- Matthias Fauconneau
-Contributed a fix for the Q3-BSP loader.
-
-- Jørgen P. Tjernø
-Contributed updated and improved xcode workspaces
-
-- drparallax
-Contributed the /samples/SimpleAssimpViewX sample
-
-- Carsten Fuchs
-Contributed a fix for the Normalize method in aiQuaternion.
-
-- dbburgess
-Contributes a Android-specific build issue: log the hardware architecture for ARM.
-
-- alfiereinre7
-Contributes a obj-fileparser fix: missing tokens in the obj-token list.
-
-- Roman Kharitonov
-Contributes a fix for the configure script environment.
-
-- Ed Diana
-Contributed AssimpDelphi (/port/AssimpDelphi).
-
-- rdb
-Contributes a bundle of fixes and improvements for the bsp-importer.
-
-- Mick P
-For contributing the De-bone postprocessing step and filing various bug reports.
-
-- Rosen Diankov
-Contributed patches to build assimp debian packages using cmake.
-
-- Mark Page
-Contributed a patch to fix the VertexTriangleAdjacency postprocessing step.
-
-- IOhannes
-Contributed the Debian build fixes ( architecture macro ).
-
-- gellule
-Several LWO and LWS fixes (pivoting). 
-
-- Marcel Metz
-GCC/Linux fixes for the SimpleOpenGL sample.
-
-- Brian Miller
-Bugfix for a compiler fix for iOS on arm.
-
-- Séverin Lemaignan
-Rewrite of PyAssimp, distutils and Python3 support
-
-- albert-wang
-Bugfixes for the collada parser
-
-- Ya ping Jin
-Bugfixes for uv-tanget calculation.
-
-- Jonne Nauha
-Ogre Binary format support
-
-- Filip Wasil, Tieto Poland Sp. z o.o.
-Android JNI asset extraction support
-
-- Richard Steffen
-Contributed ExportProperties interface
-Contributed X File exporter
-Contributed Step (stp) exporter
-
-- Thomas Iorns (mesilliac)
-Initial FBX Export support
-
-For a more detailed list just check: https://github.com/assimp/assimp/network/members
-
-
-========
-Patreons
-========
-
-Huge thanks to our Patreons!
-
-- migenius
-- Marcus
-- Cort
-- elect
-- Steffen
-
-
-===================
-Commercial Sponsors
-===================
-
-- MyDidimo (mydidimo.com): Sponsored development of FBX Export support

+ 0 - 78
thirdparty/assimp/LICENSE

@@ -1,78 +0,0 @@
-Open Asset Import Library (assimp)
-
-Copyright (c) 2006-2016, 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.
-
-
-
-******************************************************************************
-
-AN EXCEPTION applies to all files in the ./test/models-nonbsd folder.
-These are 3d models for testing purposes, from various free sources
-on the internet. They are - unless otherwise stated - copyright of
-their respective creators, which may impose additional requirements
-on the use of their work. For any of these models, see
-<model-name>.source.txt for more legal information. Contact us if you
-are a copyright holder and believe that we credited you inproperly or
-if you don't want your files to appear in the repository.
-
-
-******************************************************************************
-
-Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
-http://code.google.com/p/poly2tri/
-
-All rights reserved.
-Redistribution and use 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 Poly2Tri nor the names of its contributors may be
-  used to endorse or promote products derived from this software without specific
-  prior written permission.
-
-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.

+ 0 - 156
thirdparty/assimp/code/CApi/AssimpCExport.cpp

@@ -1,156 +0,0 @@
-/*
----------------------------------------------------------------------------
-Open Asset Import Library (assimp)
----------------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the following
-conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------------
-*/
-
-/** @file AssimpCExport.cpp
-Assimp C export interface. See Exporter.cpp for some notes.
-*/
-
-#ifndef ASSIMP_BUILD_NO_EXPORT
-
-#include "CInterfaceIOWrapper.h"
-#include <assimp/SceneCombiner.h>
-#include "Common/ScenePrivate.h"
-#include <assimp/Exporter.hpp>
-
-using namespace Assimp;
-
-// ------------------------------------------------------------------------------------------------
-ASSIMP_API size_t aiGetExportFormatCount(void)
-{
-    return Exporter().GetExportFormatCount();
-}
-
-// ------------------------------------------------------------------------------------------------
-ASSIMP_API const aiExportFormatDesc* aiGetExportFormatDescription( size_t index)
-{
-    // Note: this is valid as the index always pertains to a built-in exporter,
-    // for which the returned structure is guaranteed to be of static storage duration.
-    Exporter exporter;
-    const aiExportFormatDesc* orig( exporter.GetExportFormatDescription( index ) );
-    if (NULL == orig) {
-        return NULL;
-    }
-
-    aiExportFormatDesc *desc = new aiExportFormatDesc;
-    desc->description = new char[ strlen( orig->description ) + 1 ]();
-    ::strncpy( (char*) desc->description, orig->description, strlen( orig->description ) );
-    desc->fileExtension = new char[ strlen( orig->fileExtension ) + 1 ]();
-    ::strncpy( ( char* ) desc->fileExtension, orig->fileExtension, strlen( orig->fileExtension ) );
-    desc->id = new char[ strlen( orig->id ) + 1 ]();
-    ::strncpy( ( char* ) desc->id, orig->id, strlen( orig->id ) );
-
-    return desc;
-}
-
-// ------------------------------------------------------------------------------------------------
-ASSIMP_API void aiReleaseExportFormatDescription( const aiExportFormatDesc *desc ) {
-    if (NULL == desc) {
-        return;
-    }
-
-    delete [] desc->description;
-    delete [] desc->fileExtension;
-    delete [] desc->id;
-    delete desc;
-}
-
-// ------------------------------------------------------------------------------------------------
-ASSIMP_API void aiCopyScene(const aiScene* pIn, aiScene** pOut)
-{
-    if (!pOut || !pIn) {
-        return;
-    }
-
-    SceneCombiner::CopyScene(pOut,pIn,true);
-    ScenePriv(*pOut)->mIsCopy = true;
-}
-
-
-// ------------------------------------------------------------------------------------------------
-ASSIMP_API void aiFreeScene(const C_STRUCT aiScene* pIn)
-{
-    // note: aiReleaseImport() is also able to delete scene copies, but in addition
-    // it also handles scenes with import metadata.
-    delete pIn;
-}
-
-
-// ------------------------------------------------------------------------------------------------
-ASSIMP_API aiReturn aiExportScene( const aiScene* pScene, const char* pFormatId, const char* pFileName, unsigned int pPreprocessing )
-{
-    return ::aiExportSceneEx(pScene,pFormatId,pFileName,NULL,pPreprocessing);
-}
-
-
-// ------------------------------------------------------------------------------------------------
-ASSIMP_API aiReturn aiExportSceneEx( const aiScene* pScene, const char* pFormatId, const char* pFileName, aiFileIO* pIO, unsigned int pPreprocessing )
-{
-    Exporter exp;
-
-    if (pIO) {
-        exp.SetIOHandler(new CIOSystemWrapper(pIO));
-    }
-    return exp.Export(pScene,pFormatId,pFileName,pPreprocessing);
-}
-
-
-// ------------------------------------------------------------------------------------------------
-ASSIMP_API const C_STRUCT aiExportDataBlob* aiExportSceneToBlob( const aiScene* pScene, const char* pFormatId, unsigned int pPreprocessing  )
-{
-    Exporter exp;
-    if (!exp.ExportToBlob(pScene,pFormatId,pPreprocessing)) {
-        return NULL;
-    }
-    const aiExportDataBlob* blob = exp.GetOrphanedBlob();
-    ai_assert(blob);
-
-    return blob;
-}
-
-// ------------------------------------------------------------------------------------------------
-ASSIMP_API C_STRUCT void aiReleaseExportBlob( const aiExportDataBlob* pData )
-{
-    delete pData;
-}
-
-#endif // !ASSIMP_BUILD_NO_EXPORT

+ 0 - 136
thirdparty/assimp/code/CApi/CInterfaceIOWrapper.cpp

@@ -1,136 +0,0 @@
-/*
----------------------------------------------------------------------------
-Open Asset Import Library (assimp)
----------------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the following
-conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------------
-*/
-
-/** @file aiFileIO -> IOSystem wrapper*/
-
-#include "CInterfaceIOWrapper.h"
-
-namespace Assimp    {
-
-CIOStreamWrapper::~CIOStreamWrapper(void)
-{
-    /* Various places depend on this destructor to close the file */
-    if (mFile) {
-        mIO->mFileSystem->CloseProc(mIO->mFileSystem, mFile);
-        mFile = nullptr;
-    }
-}
-
-// ...................................................................
-size_t CIOStreamWrapper::Read(void* pvBuffer,
-    size_t pSize,
-    size_t pCount
-){
-    // need to typecast here as C has no void*
-    return mFile->ReadProc(mFile,(char*)pvBuffer,pSize,pCount);
-}
-
-// ...................................................................
-size_t CIOStreamWrapper::Write(const void* pvBuffer,
-    size_t pSize,
-    size_t pCount
-){
-    // need to typecast here as C has no void*
-    return mFile->WriteProc(mFile,(const char*)pvBuffer,pSize,pCount);
-}
-
-// ...................................................................
-aiReturn CIOStreamWrapper::Seek(size_t pOffset,
-    aiOrigin pOrigin
-){
-    return mFile->SeekProc(mFile,pOffset,pOrigin);
-}
-
-// ...................................................................
-size_t CIOStreamWrapper::Tell(void) const {
-    return mFile->TellProc(mFile);
-}
-
-// ...................................................................
-size_t CIOStreamWrapper::FileSize() const {
-    return mFile->FileSizeProc(mFile);
-}
-
-// ...................................................................
-void CIOStreamWrapper::Flush () {
-    return mFile->FlushProc(mFile);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Custom IOStream implementation for the C-API
-bool CIOSystemWrapper::Exists( const char* pFile) const {
-    aiFile* p = mFileSystem->OpenProc(mFileSystem,pFile,"rb");
-    if (p){
-        mFileSystem->CloseProc(mFileSystem,p);
-        return true;
-    }
-    return false;
-}
-
-// ...................................................................
-char CIOSystemWrapper::getOsSeparator() const {
-#ifndef _WIN32
-    return '/';
-#else
-    return '\\';
-#endif
-}
-
-// ...................................................................
-IOStream* CIOSystemWrapper::Open(const char* pFile,const char* pMode) {
-    aiFile* p = mFileSystem->OpenProc(mFileSystem,pFile,pMode);
-    if (!p) {
-        return NULL;
-    }
-    return new CIOStreamWrapper(p, this);
-}
-
-// ...................................................................
-void CIOSystemWrapper::Close( IOStream* pFile) {
-    if (!pFile) {
-        return;
-    }
-    delete pFile;
-}
-
-}

+ 0 - 99
thirdparty/assimp/code/CApi/CInterfaceIOWrapper.h

@@ -1,99 +0,0 @@
-/*
----------------------------------------------------------------------------
-Open Asset Import Library (assimp)
----------------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the following
-conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------------
-*/
-
-/** @file aiFileIO -> IOSystem wrapper*/
-
-#ifndef AI_CIOSYSTEM_H_INCLUDED
-#define AI_CIOSYSTEM_H_INCLUDED
-
-#include <assimp/cfileio.h>
-#include <assimp/IOStream.hpp>
-#include <assimp/IOSystem.hpp>
-
-namespace Assimp    {
-
-class CIOSystemWrapper;
-
-// ------------------------------------------------------------------------------------------------
-// Custom IOStream implementation for the C-API
-class CIOStreamWrapper : public IOStream
-{
-public:
-    explicit CIOStreamWrapper(aiFile* pFile, CIOSystemWrapper* io)
-        : mFile(pFile),
-        mIO(io)
-    {}
-    ~CIOStreamWrapper(void);
-
-    size_t Read(void* pvBuffer, size_t pSize, size_t pCount);
-    size_t Write(const void* pvBuffer, size_t pSize, size_t pCount);
-    aiReturn Seek(size_t pOffset, aiOrigin pOrigin);
-    size_t Tell(void) const;
-    size_t FileSize() const;
-    void Flush();
-
-private:
-    aiFile* mFile;
-    CIOSystemWrapper* mIO;
-};
-
-class CIOSystemWrapper : public IOSystem
-{
-    friend class CIOStreamWrapper;
-public:
-    explicit CIOSystemWrapper(aiFileIO* pFile)
-        : mFileSystem(pFile)
-    {}
-
-    bool Exists( const char* pFile) const;
-    char getOsSeparator() const;
-    IOStream* Open(const char* pFile,const char* pMode = "rb");
-    void Close( IOStream* pFile);
-private:
-    aiFileIO* mFileSystem;
-};
-
-}
-
-#endif
-

+ 0 - 695
thirdparty/assimp/code/Common/Assimp.cpp

@@ -1,695 +0,0 @@
-/*
----------------------------------------------------------------------------
-Open Asset Import Library (assimp)
----------------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the following
-conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------------
-*/
-/** @file  Assimp.cpp
- *  @brief Implementation of the Plain-C API
- */
-
-#include <assimp/cimport.h>
-#include <assimp/LogStream.hpp>
-#include <assimp/DefaultLogger.hpp>
-#include <assimp/Importer.hpp>
-#include <assimp/importerdesc.h>
-#include <assimp/scene.h>
-#include <assimp/GenericProperty.h>
-#include <assimp/Exceptional.h>
-#include <assimp/BaseImporter.h>
-
-#include "CApi/CInterfaceIOWrapper.h"
-#include "Importer.h"
-#include "ScenePrivate.h"
-
-#include <list>
-
-// ------------------------------------------------------------------------------------------------
-#ifndef ASSIMP_BUILD_SINGLETHREADED
-#   include <thread>
-#   include <mutex>
-#endif
-// ------------------------------------------------------------------------------------------------
-using namespace Assimp;
-
-namespace Assimp {
-    // underlying structure for aiPropertyStore
-    typedef BatchLoader::PropertyMap PropertyMap;
-
-    /** Stores the LogStream objects for all active C log streams */
-    struct mpred {
-        bool operator  () (const aiLogStream& s0, const aiLogStream& s1) const  {
-            return s0.callback<s1.callback&&s0.user<s1.user;
-        }
-    };
-    typedef std::map<aiLogStream, Assimp::LogStream*, mpred> LogStreamMap;
-
-    /** Stores the LogStream objects allocated by #aiGetPredefinedLogStream */
-    typedef std::list<Assimp::LogStream*> PredefLogStreamMap;
-
-    /** Local storage of all active log streams */
-    static LogStreamMap gActiveLogStreams;
-
-    /** Local storage of LogStreams allocated by #aiGetPredefinedLogStream */
-    static PredefLogStreamMap gPredefinedStreams;
-
-    /** Error message of the last failed import process */
-    static std::string gLastErrorString;
-
-    /** Verbose logging active or not? */
-    static aiBool gVerboseLogging = false;
-
-    /** will return all registered importers. */
-    void GetImporterInstanceList(std::vector< BaseImporter* >& out);
-
-    /** will delete all registered importers. */
-    void DeleteImporterInstanceList(std::vector< BaseImporter* >& out);
-} // namespace assimp
-
-
-#ifndef ASSIMP_BUILD_SINGLETHREADED
-/** Global mutex to manage the access to the log-stream map */
-static std::mutex gLogStreamMutex;
-#endif
-
-// ------------------------------------------------------------------------------------------------
-// Custom LogStream implementation for the C-API
-class LogToCallbackRedirector : public LogStream {
-public:
-    explicit LogToCallbackRedirector(const aiLogStream& s)
-    : stream (s)    {
-        ai_assert(NULL != s.callback);
-    }
-
-    ~LogToCallbackRedirector()  {
-#ifndef ASSIMP_BUILD_SINGLETHREADED
-        std::lock_guard<std::mutex> lock(gLogStreamMutex);
-#endif
-        // (HACK) Check whether the 'stream.user' pointer points to a
-        // custom LogStream allocated by #aiGetPredefinedLogStream.
-        // In this case, we need to delete it, too. Of course, this
-        // might cause strange problems, but the chance is quite low.
-
-        PredefLogStreamMap::iterator it = std::find(gPredefinedStreams.begin(),
-            gPredefinedStreams.end(), (Assimp::LogStream*)stream.user);
-
-        if (it != gPredefinedStreams.end()) {
-            delete *it;
-            gPredefinedStreams.erase(it);
-        }
-    }
-
-    /** @copydoc LogStream::write */
-    void write(const char* message) {
-        stream.callback(message,stream.user);
-    }
-
-private:
-    aiLogStream stream;
-};
-
-// ------------------------------------------------------------------------------------------------
-void ReportSceneNotFoundError() {
-    ASSIMP_LOG_ERROR("Unable to find the Assimp::Importer for this aiScene. "
-        "The C-API does not accept scenes produced by the C++ API and vice versa");
-
-    ai_assert(false);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Reads the given file and returns its content.
-const aiScene* aiImportFile( const char* pFile, unsigned int pFlags) {
-    return aiImportFileEx(pFile,pFlags,NULL);
-}
-
-// ------------------------------------------------------------------------------------------------
-const aiScene* aiImportFileEx( const char* pFile, unsigned int pFlags,  aiFileIO* pFS) {
-    return aiImportFileExWithProperties(pFile, pFlags, pFS, NULL);
-}
-
-// ------------------------------------------------------------------------------------------------
-const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFlags, 
-        aiFileIO* pFS, const aiPropertyStore* props) {
-    ai_assert(NULL != pFile);
-
-    const aiScene* scene = NULL;
-    ASSIMP_BEGIN_EXCEPTION_REGION();
-
-    // create an Importer for this file
-    Assimp::Importer* imp = new Assimp::Importer();
-
-    // copy properties
-    if(props) {
-        const PropertyMap* pp = reinterpret_cast<const PropertyMap*>(props);
-        ImporterPimpl* pimpl = imp->Pimpl();
-        pimpl->mIntProperties = pp->ints;
-        pimpl->mFloatProperties = pp->floats;
-        pimpl->mStringProperties = pp->strings;
-        pimpl->mMatrixProperties = pp->matrices;
-    }
-    // setup a custom IO system if necessary
-    if (pFS) {
-        imp->SetIOHandler( new CIOSystemWrapper (pFS) );
-    }
-
-    // and have it read the file
-    scene = imp->ReadFile( pFile, pFlags);
-
-    // if succeeded, store the importer in the scene and keep it alive
-    if( scene)  {
-        ScenePrivateData* priv = const_cast<ScenePrivateData*>( ScenePriv(scene) );
-        priv->mOrigImporter = imp;
-    } else {
-        // if failed, extract error code and destroy the import
-        gLastErrorString = imp->GetErrorString();
-        delete imp;
-    }
-
-    // return imported data. If the import failed the pointer is NULL anyways
-    ASSIMP_END_EXCEPTION_REGION(const aiScene*);
-    
-    return scene;
-}
-
-// ------------------------------------------------------------------------------------------------
-const aiScene* aiImportFileFromMemory(
-    const char* pBuffer,
-    unsigned int pLength,
-    unsigned int pFlags,
-    const char* pHint)
-{
-    return aiImportFileFromMemoryWithProperties(pBuffer, pLength, pFlags, pHint, NULL);
-}
-
-// ------------------------------------------------------------------------------------------------
-const aiScene* aiImportFileFromMemoryWithProperties(
-    const char* pBuffer,
-    unsigned int pLength,
-    unsigned int pFlags,
-    const char* pHint,
-    const aiPropertyStore* props)
-{
-    ai_assert( NULL != pBuffer );
-    ai_assert( 0 != pLength );
-
-    const aiScene* scene = NULL;
-    ASSIMP_BEGIN_EXCEPTION_REGION();
-
-    // create an Importer for this file
-    Assimp::Importer* imp = new Assimp::Importer();
-
-    // copy properties
-    if(props) {
-        const PropertyMap* pp = reinterpret_cast<const PropertyMap*>(props);
-        ImporterPimpl* pimpl = imp->Pimpl();
-        pimpl->mIntProperties = pp->ints;
-        pimpl->mFloatProperties = pp->floats;
-        pimpl->mStringProperties = pp->strings;
-        pimpl->mMatrixProperties = pp->matrices;
-    }
-
-    // and have it read the file from the memory buffer
-    scene = imp->ReadFileFromMemory( pBuffer, pLength, pFlags,pHint);
-
-    // if succeeded, store the importer in the scene and keep it alive
-    if( scene)  {
-         ScenePrivateData* priv = const_cast<ScenePrivateData*>( ScenePriv(scene) );
-         priv->mOrigImporter = imp;
-    }
-    else    {
-        // if failed, extract error code and destroy the import
-        gLastErrorString = imp->GetErrorString();
-        delete imp;
-    }
-    // return imported data. If the import failed the pointer is NULL anyways
-    ASSIMP_END_EXCEPTION_REGION(const aiScene*);
-    return scene;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Releases all resources associated with the given import process.
-void aiReleaseImport( const aiScene* pScene)
-{
-    if (!pScene) {
-        return;
-    }
-
-    ASSIMP_BEGIN_EXCEPTION_REGION();
-
-    // find the importer associated with this data
-    const ScenePrivateData* priv = ScenePriv(pScene);
-    if( !priv || !priv->mOrigImporter)  {
-        delete pScene;
-    }
-    else {
-        // deleting the Importer also deletes the scene
-        // Note: the reason that this is not written as 'delete priv->mOrigImporter'
-        // is a suspected bug in gcc 4.4+ (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52339)
-        Importer* importer = priv->mOrigImporter;
-        delete importer;
-    }
-
-    ASSIMP_END_EXCEPTION_REGION(void);
-}
-
-// ------------------------------------------------------------------------------------------------
-ASSIMP_API const aiScene* aiApplyPostProcessing(const aiScene* pScene,
-    unsigned int pFlags)
-{
-    const aiScene* sc = NULL;
-
-
-    ASSIMP_BEGIN_EXCEPTION_REGION();
-
-    // find the importer associated with this data
-    const ScenePrivateData* priv = ScenePriv(pScene);
-    if( !priv || !priv->mOrigImporter)  {
-        ReportSceneNotFoundError();
-        return NULL;
-    }
-
-    sc = priv->mOrigImporter->ApplyPostProcessing(pFlags);
-
-    if (!sc) {
-        aiReleaseImport(pScene);
-        return NULL;
-    }
-
-    ASSIMP_END_EXCEPTION_REGION(const aiScene*);
-    return sc;
-}
-
-// ------------------------------------------------------------------------------------------------
-ASSIMP_API const aiScene *aiApplyCustomizedPostProcessing( const aiScene *scene,
-                                                           BaseProcess* process,
-                                                           bool requestValidation ) {
-    const aiScene* sc( NULL );
-
-    ASSIMP_BEGIN_EXCEPTION_REGION();
-
-    // find the importer associated with this data
-    const ScenePrivateData* priv = ScenePriv( scene );
-    if ( NULL == priv || NULL == priv->mOrigImporter ) {
-        ReportSceneNotFoundError();
-        return NULL;
-    }
-
-    sc = priv->mOrigImporter->ApplyCustomizedPostProcessing( process, requestValidation );
-
-    if ( !sc ) {
-        aiReleaseImport( scene );
-        return NULL;
-    }
-
-    ASSIMP_END_EXCEPTION_REGION( const aiScene* );
-
-    return sc;
-}
-
-// ------------------------------------------------------------------------------------------------
-void CallbackToLogRedirector (const char* msg, char* dt)
-{
-    ai_assert( NULL != msg );
-    ai_assert( NULL != dt );
-    LogStream* s = (LogStream*)dt;
-
-    s->write(msg);
-}
-
-// ------------------------------------------------------------------------------------------------
-ASSIMP_API aiLogStream aiGetPredefinedLogStream(aiDefaultLogStream pStream,const char* file)
-{
-    aiLogStream sout;
-
-    ASSIMP_BEGIN_EXCEPTION_REGION();
-    LogStream* stream = LogStream::createDefaultStream(pStream,file);
-    if (!stream) {
-        sout.callback = NULL;
-        sout.user = NULL;
-    }
-    else {
-        sout.callback = &CallbackToLogRedirector;
-        sout.user = (char*)stream;
-    }
-    gPredefinedStreams.push_back(stream);
-    ASSIMP_END_EXCEPTION_REGION(aiLogStream);
-    return sout;
-}
-
-// ------------------------------------------------------------------------------------------------
-ASSIMP_API void aiAttachLogStream( const aiLogStream* stream )
-{
-    ASSIMP_BEGIN_EXCEPTION_REGION();
-
-#ifndef ASSIMP_BUILD_SINGLETHREADED
-    std::lock_guard<std::mutex> lock(gLogStreamMutex);
-#endif
-
-    LogStream* lg = new LogToCallbackRedirector(*stream);
-    gActiveLogStreams[*stream] = lg;
-
-    if (DefaultLogger::isNullLogger()) {
-        DefaultLogger::create(NULL,(gVerboseLogging == AI_TRUE ? Logger::VERBOSE : Logger::NORMAL));
-    }
-    DefaultLogger::get()->attachStream(lg);
-    ASSIMP_END_EXCEPTION_REGION(void);
-}
-
-// ------------------------------------------------------------------------------------------------
-ASSIMP_API aiReturn aiDetachLogStream( const aiLogStream* stream)
-{
-    ASSIMP_BEGIN_EXCEPTION_REGION();
-
-#ifndef ASSIMP_BUILD_SINGLETHREADED
-    std::lock_guard<std::mutex> lock(gLogStreamMutex);
-#endif
-    // find the log-stream associated with this data
-    LogStreamMap::iterator it = gActiveLogStreams.find( *stream);
-    // it should be there... else the user is playing fools with us
-    if( it == gActiveLogStreams.end())  {
-        return AI_FAILURE;
-    }
-    DefaultLogger::get()->detatchStream( it->second );
-    delete it->second;
-
-    gActiveLogStreams.erase( it);
-
-    if (gActiveLogStreams.empty()) {
-        DefaultLogger::kill();
-    }
-    ASSIMP_END_EXCEPTION_REGION(aiReturn);
-    return AI_SUCCESS;
-}
-
-// ------------------------------------------------------------------------------------------------
-ASSIMP_API void aiDetachAllLogStreams(void)
-{
-    ASSIMP_BEGIN_EXCEPTION_REGION();
-#ifndef ASSIMP_BUILD_SINGLETHREADED
-    std::lock_guard<std::mutex> lock(gLogStreamMutex);
-#endif
-    Logger *logger( DefaultLogger::get() );
-    if ( NULL == logger ) {
-        return;
-    }
-
-    for (LogStreamMap::iterator it = gActiveLogStreams.begin(); it != gActiveLogStreams.end(); ++it) {
-        logger->detatchStream( it->second );
-        delete it->second;
-    }
-    gActiveLogStreams.clear();
-    DefaultLogger::kill();
-
-    ASSIMP_END_EXCEPTION_REGION(void);
-}
-
-// ------------------------------------------------------------------------------------------------
-ASSIMP_API void aiEnableVerboseLogging(aiBool d)
-{
-    if (!DefaultLogger::isNullLogger()) {
-        DefaultLogger::get()->setLogSeverity((d == AI_TRUE ? Logger::VERBOSE : Logger::NORMAL));
-    }
-    gVerboseLogging = d;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Returns the error text of the last failed import process.
-const char* aiGetErrorString()
-{
-    return gLastErrorString.c_str();
-}
-
-// -----------------------------------------------------------------------------------------------
-// Return the description of a importer given its index
-const aiImporterDesc* aiGetImportFormatDescription( size_t pIndex)
-{
-    return Importer().GetImporterInfo(pIndex);
-}
-
-// -----------------------------------------------------------------------------------------------
-// Return the number of importers
-size_t aiGetImportFormatCount(void)
-{
-    return Importer().GetImporterCount();
-}
-
-// ------------------------------------------------------------------------------------------------
-// Returns the error text of the last failed import process.
-aiBool aiIsExtensionSupported(const char* szExtension)
-{
-    ai_assert(NULL != szExtension);
-    aiBool candoit=AI_FALSE;
-    ASSIMP_BEGIN_EXCEPTION_REGION();
-
-    // FIXME: no need to create a temporary Importer instance just for that ..
-    Assimp::Importer tmp;
-    candoit = tmp.IsExtensionSupported(std::string(szExtension)) ? AI_TRUE : AI_FALSE;
-
-    ASSIMP_END_EXCEPTION_REGION(aiBool);
-    return candoit;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Get a list of all file extensions supported by ASSIMP
-void aiGetExtensionList(aiString* szOut)
-{
-    ai_assert(NULL != szOut);
-    ASSIMP_BEGIN_EXCEPTION_REGION();
-
-    // FIXME: no need to create a temporary Importer instance just for that ..
-    Assimp::Importer tmp;
-    tmp.GetExtensionList(*szOut);
-
-    ASSIMP_END_EXCEPTION_REGION(void);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Get the memory requirements for a particular import.
-void aiGetMemoryRequirements(const C_STRUCT aiScene* pIn,
-    C_STRUCT aiMemoryInfo* in)
-{
-    ASSIMP_BEGIN_EXCEPTION_REGION();
-
-    // find the importer associated with this data
-    const ScenePrivateData* priv = ScenePriv(pIn);
-    if( !priv || !priv->mOrigImporter)  {
-        ReportSceneNotFoundError();
-        return;
-    }
-
-    return priv->mOrigImporter->GetMemoryRequirements(*in);
-    ASSIMP_END_EXCEPTION_REGION(void);
-}
-
-// ------------------------------------------------------------------------------------------------
-ASSIMP_API aiPropertyStore* aiCreatePropertyStore(void)
-{
-    return reinterpret_cast<aiPropertyStore*>( new PropertyMap() );
-}
-
-// ------------------------------------------------------------------------------------------------
-ASSIMP_API void aiReleasePropertyStore(aiPropertyStore* p)
-{
-    delete reinterpret_cast<PropertyMap*>(p);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Importer::SetPropertyInteger
-ASSIMP_API void aiSetImportPropertyInteger(aiPropertyStore* p, const char* szName, int value)
-{
-    ASSIMP_BEGIN_EXCEPTION_REGION();
-    PropertyMap* pp = reinterpret_cast<PropertyMap*>(p);
-    SetGenericProperty<int>(pp->ints,szName,value);
-    ASSIMP_END_EXCEPTION_REGION(void);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Importer::SetPropertyFloat
-ASSIMP_API void aiSetImportPropertyFloat(aiPropertyStore* p, const char* szName, ai_real value)
-{
-    ASSIMP_BEGIN_EXCEPTION_REGION();
-    PropertyMap* pp = reinterpret_cast<PropertyMap*>(p);
-    SetGenericProperty<ai_real>(pp->floats,szName,value);
-    ASSIMP_END_EXCEPTION_REGION(void);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Importer::SetPropertyString
-ASSIMP_API void aiSetImportPropertyString(aiPropertyStore* p, const char* szName,
-    const C_STRUCT aiString* st)
-{
-    if (!st) {
-        return;
-    }
-    ASSIMP_BEGIN_EXCEPTION_REGION();
-    PropertyMap* pp = reinterpret_cast<PropertyMap*>(p);
-    SetGenericProperty<std::string>(pp->strings,szName,std::string(st->C_Str()));
-    ASSIMP_END_EXCEPTION_REGION(void);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Importer::SetPropertyMatrix
-ASSIMP_API void aiSetImportPropertyMatrix(aiPropertyStore* p, const char* szName,
-    const C_STRUCT aiMatrix4x4* mat)
-{
-    if (!mat) {
-        return;
-    }
-    ASSIMP_BEGIN_EXCEPTION_REGION();
-    PropertyMap* pp = reinterpret_cast<PropertyMap*>(p);
-    SetGenericProperty<aiMatrix4x4>(pp->matrices,szName,*mat);
-    ASSIMP_END_EXCEPTION_REGION(void);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Rotation matrix to quaternion
-ASSIMP_API void aiCreateQuaternionFromMatrix(aiQuaternion* quat,const aiMatrix3x3* mat)
-{
-    ai_assert( NULL != quat );
-    ai_assert( NULL != mat );
-    *quat = aiQuaternion(*mat);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Matrix decomposition
-ASSIMP_API void aiDecomposeMatrix(const aiMatrix4x4* mat,aiVector3D* scaling,
-    aiQuaternion* rotation,
-    aiVector3D* position)
-{
-    ai_assert( NULL != rotation );
-    ai_assert( NULL != position );
-    ai_assert( NULL != scaling );
-    ai_assert( NULL != mat );
-    mat->Decompose(*scaling,*rotation,*position);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Matrix transpose
-ASSIMP_API void aiTransposeMatrix3(aiMatrix3x3* mat)
-{
-    ai_assert(NULL != mat);
-    mat->Transpose();
-}
-
-// ------------------------------------------------------------------------------------------------
-ASSIMP_API void aiTransposeMatrix4(aiMatrix4x4* mat)
-{
-    ai_assert(NULL != mat);
-    mat->Transpose();
-}
-
-// ------------------------------------------------------------------------------------------------
-// Vector transformation
-ASSIMP_API void aiTransformVecByMatrix3(aiVector3D* vec,
-    const aiMatrix3x3* mat)
-{
-    ai_assert( NULL != mat );
-    ai_assert( NULL != vec);
-    *vec *= (*mat);
-}
-
-// ------------------------------------------------------------------------------------------------
-ASSIMP_API void aiTransformVecByMatrix4(aiVector3D* vec,
-    const aiMatrix4x4* mat)
-{
-    ai_assert( NULL != mat );
-    ai_assert( NULL != vec );
-
-    *vec *= (*mat);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Matrix multiplication
-ASSIMP_API void aiMultiplyMatrix4(
-    aiMatrix4x4* dst,
-    const aiMatrix4x4* src)
-{
-    ai_assert( NULL != dst );
-    ai_assert( NULL != src );
-    *dst = (*dst) * (*src);
-}
-
-// ------------------------------------------------------------------------------------------------
-ASSIMP_API void aiMultiplyMatrix3(
-    aiMatrix3x3* dst,
-    const aiMatrix3x3* src)
-{
-    ai_assert( NULL != dst );
-    ai_assert( NULL != src );
-    *dst = (*dst) * (*src);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Matrix identity
-ASSIMP_API void aiIdentityMatrix3(
-    aiMatrix3x3* mat)
-{
-    ai_assert(NULL != mat);
-    *mat = aiMatrix3x3();
-}
-
-// ------------------------------------------------------------------------------------------------
-ASSIMP_API void aiIdentityMatrix4(
-    aiMatrix4x4* mat)
-{
-    ai_assert(NULL != mat);
-    *mat = aiMatrix4x4();
-}
-
-// ------------------------------------------------------------------------------------------------
-ASSIMP_API C_STRUCT const aiImporterDesc* aiGetImporterDesc( const char *extension ) {
-    if( NULL == extension ) {
-        return NULL;
-    }
-    const aiImporterDesc *desc( NULL );
-    std::vector< BaseImporter* > out;
-    GetImporterInstanceList( out );
-    for( size_t i = 0; i < out.size(); ++i ) {
-        if( 0 == strncmp( out[ i ]->GetInfo()->mFileExtensions, extension, strlen( extension ) ) ) {
-            desc = out[ i ]->GetInfo();
-            break;
-        }
-    }
-
-    DeleteImporterInstanceList(out);
-
-    return desc;
-}
-
-// ------------------------------------------------------------------------------------------------

+ 0 - 656
thirdparty/assimp/code/Common/BaseImporter.cpp

@@ -1,656 +0,0 @@
-/*
----------------------------------------------------------------------------
-Open Asset Import Library (assimp)
----------------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the following
-conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------------
-*/
-
-/** @file  BaseImporter.cpp
- *  @brief Implementation of BaseImporter
- */
-
-#include <assimp/BaseImporter.h>
-#include <assimp/ParsingUtils.h>
-#include "FileSystemFilter.h"
-#include "Importer.h"
-#include <assimp/ByteSwapper.h>
-#include <assimp/scene.h>
-#include <assimp/Importer.hpp>
-#include <assimp/postprocess.h>
-#include <assimp/importerdesc.h>
-
-#include <ios>
-#include <list>
-#include <memory>
-#include <sstream>
-#include <cctype>
-
-using namespace Assimp;
-
-// ------------------------------------------------------------------------------------------------
-// Constructor to be privately used by Importer
-BaseImporter::BaseImporter() AI_NO_EXCEPT
-: m_progress() {
-    /**
-    * Assimp Importer
-    * unit conversions available
-    * if you need another measurment unit add it below.
-    * it's currently defined in assimp that we prefer meters.
-    *
-    * NOTE: Initialised here rather than in the header file
-    * to workaround a VS2013 bug with brace initialisers
-    * */
-    importerUnits[ImporterUnits::M] = 1.0;
-    importerUnits[ImporterUnits::CM] = 0.01;
-    importerUnits[ImporterUnits::MM] = 0.001;
-    importerUnits[ImporterUnits::INCHES] = 0.0254;
-    importerUnits[ImporterUnits::FEET] = 0.3048;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
-BaseImporter::~BaseImporter() {
-    // nothing to do here
-}
-
-void BaseImporter::UpdateImporterScale( Importer* pImp )
-{
-    ai_assert(pImp != nullptr);
-    ai_assert(importerScale != 0.0);
-    ai_assert(fileScale != 0.0);
-
-    double activeScale = importerScale * fileScale;
-
-    // Set active scaling
-    pImp->SetPropertyFloat( AI_CONFIG_APP_SCALE_KEY, static_cast<float>( activeScale) );
-
-    ASSIMP_LOG_DEBUG_F("UpdateImporterScale scale set: %f", activeScale );
-}
-
-// ------------------------------------------------------------------------------------------------
-// Imports the given file and returns the imported data.
-aiScene* BaseImporter::ReadFile(Importer* pImp, const std::string& pFile, IOSystem* pIOHandler) {
-
-
-    m_progress = pImp->GetProgressHandler();
-    if (nullptr == m_progress) {
-        return nullptr;
-    }
-
-    ai_assert(m_progress);
-
-    // Gather configuration properties for this run
-    SetupProperties( pImp );
-
-    // Construct a file system filter to improve our success ratio at reading external files
-    FileSystemFilter filter(pFile,pIOHandler);
-
-    // create a scene object to hold the data
-    std::unique_ptr<aiScene> sc(new aiScene());
-
-    // dispatch importing
-    try
-    {
-        InternReadFile( pFile, sc.get(), &filter);
-
-        // Calculate import scale hook - required because pImp not available anywhere else
-        // passes scale into ScaleProcess
-        UpdateImporterScale(pImp);
-
-
-    } catch( const std::exception& err )    {
-        // extract error description
-        m_ErrorText = err.what();
-        ASSIMP_LOG_ERROR(m_ErrorText);
-        return nullptr;
-    }
-
-    // return what we gathered from the import.
-    return sc.release();
-}
-
-// ------------------------------------------------------------------------------------------------
-void BaseImporter::SetupProperties(const Importer* pImp)
-{
-    // the default implementation does nothing
-}
-
-// ------------------------------------------------------------------------------------------------
-void BaseImporter::GetExtensionList(std::set<std::string>& extensions) {
-    const aiImporterDesc* desc = GetInfo();
-    ai_assert(desc != nullptr);
-
-    const char* ext = desc->mFileExtensions;
-    ai_assert(ext != nullptr );
-
-    const char* last = ext;
-    do {
-        if (!*ext || *ext == ' ') {
-            extensions.insert(std::string(last,ext-last));
-            ai_assert(ext-last > 0);
-            last = ext;
-            while(*last == ' ') {
-                ++last;
-            }
-        }
-    }
-    while(*ext++);
-}
-
-// ------------------------------------------------------------------------------------------------
-/*static*/ bool BaseImporter::SearchFileHeaderForToken( IOSystem* pIOHandler,
-    const std::string&  pFile,
-    const char**        tokens,
-    unsigned int        numTokens,
-    unsigned int        searchBytes /* = 200 */,
-    bool                tokensSol /* false */,
-    bool                noAlphaBeforeTokens /* false */)
-{
-    ai_assert( nullptr != tokens );
-    ai_assert( 0 != numTokens );
-    ai_assert( 0 != searchBytes);
-
-    if ( nullptr == pIOHandler ) {
-        return false;
-    }
-
-    std::unique_ptr<IOStream> pStream (pIOHandler->Open(pFile));
-    if (pStream.get() ) {
-        // read 200 characters from the file
-        std::unique_ptr<char[]> _buffer (new char[searchBytes+1 /* for the '\0' */]);
-        char *buffer( _buffer.get() );
-        const size_t read( pStream->Read(buffer,1,searchBytes) );
-        if( 0 == read ) {
-            return false;
-        }
-
-        for( size_t i = 0; i < read; ++i ) {
-            buffer[ i ] = static_cast<char>( ::tolower( buffer[ i ] ) );
-        }
-
-        // It is not a proper handling of unicode files here ...
-        // ehm ... but it works in most cases.
-        char* cur = buffer,*cur2 = buffer,*end = &buffer[read];
-        while (cur != end)  {
-            if( *cur ) {
-                *cur2++ = *cur;
-            }
-            ++cur;
-        }
-        *cur2 = '\0';
-
-        std::string token;
-        for (unsigned int i = 0; i < numTokens; ++i ) {
-            ai_assert( nullptr != tokens[i] );
-            const size_t len( strlen( tokens[ i ] ) );
-            token.clear();
-            const char *ptr( tokens[ i ] );
-            for ( size_t tokIdx = 0; tokIdx < len; ++tokIdx ) {
-                token.push_back( static_cast<char>( tolower( *ptr ) ) );
-                ++ptr;
-            }
-            const char* r = strstr( buffer, token.c_str() );
-            if( !r ) {
-                continue;
-            }
-            // We need to make sure that we didn't accidentially identify the end of another token as our token,
-            // e.g. in a previous version the "gltf " present in some gltf files was detected as "f "
-            if (noAlphaBeforeTokens && (r != buffer && isalpha(r[-1]))) {
-                continue;
-            }
-            // We got a match, either we don't care where it is, or it happens to
-            // be in the beginning of the file / line
-            if (!tokensSol || r == buffer || r[-1] == '\r' || r[-1] == '\n') {
-                ASSIMP_LOG_DEBUG_F( "Found positive match for header keyword: ", tokens[i] );
-                return true;
-            }
-        }
-    }
-
-    return false;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Simple check for file extension
-/*static*/ bool BaseImporter::SimpleExtensionCheck (const std::string& pFile,
-    const char* ext0,
-    const char* ext1,
-    const char* ext2)
-{
-    std::string::size_type pos = pFile.find_last_of('.');
-
-    // no file extension - can't read
-    if( pos == std::string::npos)
-        return false;
-
-    const char* ext_real = & pFile[ pos+1 ];
-    if( !ASSIMP_stricmp(ext_real,ext0) )
-        return true;
-
-    // check for other, optional, file extensions
-    if (ext1 && !ASSIMP_stricmp(ext_real,ext1))
-        return true;
-
-    if (ext2 && !ASSIMP_stricmp(ext_real,ext2))
-        return true;
-
-    return false;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Get file extension from path
-std::string BaseImporter::GetExtension( const std::string& file ) {
-    std::string::size_type pos = file.find_last_of('.');
-
-    // no file extension at all
-    if (pos == std::string::npos) {
-        return "";
-    }
-
-
-    // thanks to Andy Maloney for the hint
-    std::string ret = file.substr( pos + 1 );
-    std::transform( ret.begin(), ret.end(), ret.begin(), ToLower<char>);
-
-    return ret;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Check for magic bytes at the beginning of the file.
-/* static */ bool BaseImporter::CheckMagicToken(IOSystem* pIOHandler, const std::string& pFile,
-    const void* _magic, unsigned int num, unsigned int offset, unsigned int size)
-{
-    ai_assert( size <= 16 );
-    ai_assert( _magic );
-
-    if (!pIOHandler) {
-        return false;
-    }
-    union {
-        const char* magic;
-        const uint16_t* magic_u16;
-        const uint32_t* magic_u32;
-    };
-    magic = reinterpret_cast<const char*>(_magic);
-    std::unique_ptr<IOStream> pStream (pIOHandler->Open(pFile));
-    if (pStream.get() ) {
-
-        // skip to offset
-        pStream->Seek(offset,aiOrigin_SET);
-
-        // read 'size' characters from the file
-        union {
-            char data[16];
-            uint16_t data_u16[8];
-            uint32_t data_u32[4];
-        };
-        if(size != pStream->Read(data,1,size)) {
-            return false;
-        }
-
-        for (unsigned int i = 0; i < num; ++i) {
-            // also check against big endian versions of tokens with size 2,4
-            // that's just for convenience, the chance that we cause conflicts
-            // is quite low and it can save some lines and prevent nasty bugs
-            if (2 == size) {
-                uint16_t rev = *magic_u16;
-                ByteSwap::Swap(&rev);
-                if (data_u16[0] == *magic_u16 || data_u16[0] == rev) {
-                    return true;
-                }
-            }
-            else if (4 == size) {
-                uint32_t rev = *magic_u32;
-                ByteSwap::Swap(&rev);
-                if (data_u32[0] == *magic_u32 || data_u32[0] == rev) {
-                    return true;
-                }
-            }
-            else {
-                // any length ... just compare
-                if(!memcmp(magic,data,size)) {
-                    return true;
-                }
-            }
-            magic += size;
-        }
-    }
-    return false;
-}
-
-#ifdef ASSIMP_USE_HUNTER
-#  include <utf8/utf8.h>
-#else
-#  include "../contrib/utf8cpp/source/utf8.h"
-#endif
-
-// ------------------------------------------------------------------------------------------------
-// Convert to UTF8 data
-void BaseImporter::ConvertToUTF8(std::vector<char>& data)
-{
-    //ConversionResult result;
-    if(data.size() < 8) {
-        throw DeadlyImportError("File is too small");
-    }
-
-    // UTF 8 with BOM
-    if((uint8_t)data[0] == 0xEF && (uint8_t)data[1] == 0xBB && (uint8_t)data[2] == 0xBF) {
-        ASSIMP_LOG_DEBUG("Found UTF-8 BOM ...");
-
-        std::copy(data.begin()+3,data.end(),data.begin());
-        data.resize(data.size()-3);
-        return;
-    }
-    
-    
-    // UTF 32 BE with BOM
-    if(*((uint32_t*)&data.front()) == 0xFFFE0000) {
-
-        // swap the endianness ..
-        for(uint32_t* p = (uint32_t*)&data.front(), *end = (uint32_t*)&data.back(); p <= end; ++p) {
-            AI_SWAP4P(p);
-        }
-    }
-
-    // UTF 32 LE with BOM
-    if(*((uint32_t*)&data.front()) == 0x0000FFFE) {
-        ASSIMP_LOG_DEBUG("Found UTF-32 BOM ...");
-
-        std::vector<char> output;
-        int *ptr = (int*)&data[ 0 ];
-        int *end = ptr + ( data.size() / sizeof(int) ) +1;
-        utf8::utf32to8( ptr, end, back_inserter(output));
-        return;
-    }
-
-    // UTF 16 BE with BOM
-    if(*((uint16_t*)&data.front()) == 0xFFFE) {
-
-        // swap the endianness ..
-        for(uint16_t* p = (uint16_t*)&data.front(), *end = (uint16_t*)&data.back(); p <= end; ++p) {
-            ByteSwap::Swap2(p);
-        }
-    }
-
-    // UTF 16 LE with BOM
-    if(*((uint16_t*)&data.front()) == 0xFEFF) {
-        ASSIMP_LOG_DEBUG("Found UTF-16 BOM ...");
-
-        std::vector<unsigned char> output;
-        utf8::utf16to8(data.begin(), data.end(), back_inserter(output));
-        return;
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-// Convert to UTF8 data to ISO-8859-1
-void BaseImporter::ConvertUTF8toISO8859_1(std::string& data)
-{
-    size_t size = data.size();
-    size_t i = 0, j = 0;
-
-    while(i < size) {
-        if ((unsigned char) data[i] < (size_t) 0x80) {
-            data[j] = data[i];
-        } else if(i < size - 1) {
-            if((unsigned char) data[i] == 0xC2) {
-                data[j] = data[++i];
-            } else if((unsigned char) data[i] == 0xC3) {
-                data[j] = ((unsigned char) data[++i] + 0x40);
-            } else {
-                std::stringstream stream;
-                stream << "UTF8 code " << std::hex << data[i] << data[i + 1] << " can not be converted into ISA-8859-1.";
-                ASSIMP_LOG_ERROR( stream.str() );
-
-                data[j++] = data[i++];
-                data[j] = data[i];
-            }
-        } else {
-            ASSIMP_LOG_ERROR("UTF8 code but only one character remaining");
-
-            data[j] = data[i];
-        }
-
-        i++; j++;
-    }
-
-    data.resize(j);
-}
-
-// ------------------------------------------------------------------------------------------------
-void BaseImporter::TextFileToBuffer(IOStream* stream,
-    std::vector<char>& data,
-    TextFileMode mode)
-{
-    ai_assert(nullptr != stream);
-
-    const size_t fileSize = stream->FileSize();
-    if (mode == FORBID_EMPTY) {
-        if(!fileSize) {
-            throw DeadlyImportError("File is empty");
-        }
-    }
-
-    data.reserve(fileSize+1);
-    data.resize(fileSize);
-    if(fileSize > 0) {
-        if(fileSize != stream->Read( &data[0], 1, fileSize)) {
-            throw DeadlyImportError("File read error");
-        }
-
-        ConvertToUTF8(data);
-    }
-
-    // append a binary zero to simplify string parsing
-    data.push_back(0);
-}
-
-// ------------------------------------------------------------------------------------------------
-namespace Assimp {
-    // Represents an import request
-    struct LoadRequest {
-        LoadRequest(const std::string& _file, unsigned int _flags,const BatchLoader::PropertyMap* _map, unsigned int _id)
-        : file(_file)
-        , flags(_flags)
-        , refCnt(1)
-        , scene(NULL)
-        , loaded(false)
-        , id(_id) {
-            if ( _map ) {
-                map = *_map;
-            }
-        }
-
-        bool operator== ( const std::string& f ) const {
-            return file == f;
-        }
-
-        const std::string        file;
-        unsigned int             flags;
-        unsigned int             refCnt;
-        aiScene                 *scene;
-        bool                     loaded;
-        BatchLoader::PropertyMap map;
-        unsigned int             id;
-    };
-}
-
-// ------------------------------------------------------------------------------------------------
-// BatchLoader::pimpl data structure
-struct Assimp::BatchData {
-    BatchData( IOSystem* pIO, bool validate )
-    : pIOSystem( pIO )
-    , pImporter( nullptr )
-    , next_id(0xffff)
-    , validate( validate ) {
-        ai_assert( nullptr != pIO );
-        
-        pImporter = new Importer();
-        pImporter->SetIOHandler( pIO );
-    }
-
-    ~BatchData() {
-        pImporter->SetIOHandler( nullptr ); /* get pointer back into our possession */
-        delete pImporter;
-    }
-
-    // IO system to be used for all imports
-    IOSystem* pIOSystem;
-
-    // Importer used to load all meshes
-    Importer* pImporter;
-
-    // List of all imports
-    std::list<LoadRequest> requests;
-
-    // Base path
-    std::string pathBase;
-
-    // Id for next item
-    unsigned int next_id;
-
-    // Validation enabled state
-    bool validate;
-};
-
-typedef std::list<LoadRequest>::iterator LoadReqIt;
-
-// ------------------------------------------------------------------------------------------------
-BatchLoader::BatchLoader(IOSystem* pIO, bool validate ) {
-    ai_assert(nullptr != pIO);
-
-    m_data = new BatchData( pIO, validate );
-}
-
-// ------------------------------------------------------------------------------------------------
-BatchLoader::~BatchLoader()
-{
-    // delete all scenes what have not been polled by the user
-    for ( LoadReqIt it = m_data->requests.begin();it != m_data->requests.end(); ++it) {
-        delete (*it).scene;
-    }
-    delete m_data;
-}
-
-// ------------------------------------------------------------------------------------------------
-void BatchLoader::setValidation( bool enabled ) {
-    m_data->validate = enabled;
-}
-
-// ------------------------------------------------------------------------------------------------
-bool BatchLoader::getValidation() const {
-    return m_data->validate;
-}
-
-// ------------------------------------------------------------------------------------------------
-unsigned int BatchLoader::AddLoadRequest(const std::string& file,
-    unsigned int steps /*= 0*/, const PropertyMap* map /*= NULL*/)
-{
-    ai_assert(!file.empty());
-
-    // check whether we have this loading request already
-    for ( LoadReqIt it = m_data->requests.begin();it != m_data->requests.end(); ++it)  {
-        // Call IOSystem's path comparison function here
-        if ( m_data->pIOSystem->ComparePaths((*it).file,file)) {
-            if (map) {
-                if ( !( ( *it ).map == *map ) ) {
-                    continue;
-                }
-            }
-            else if ( !( *it ).map.empty() ) {
-                continue;
-            }
-
-            (*it).refCnt++;
-            return (*it).id;
-        }
-    }
-
-    // no, we don't have it. So add it to the queue ...
-    m_data->requests.push_back(LoadRequest(file,steps,map, m_data->next_id));
-    return m_data->next_id++;
-}
-
-// ------------------------------------------------------------------------------------------------
-aiScene* BatchLoader::GetImport( unsigned int which )
-{
-    for ( LoadReqIt it = m_data->requests.begin();it != m_data->requests.end(); ++it) {
-        if ((*it).id == which && (*it).loaded)  {
-            aiScene* sc = (*it).scene;
-            if (!(--(*it).refCnt))  {
-                m_data->requests.erase(it);
-            }
-            return sc;
-        }
-    }
-    return nullptr;
-}
-
-
-
-// ------------------------------------------------------------------------------------------------
-void BatchLoader::LoadAll()
-{
-    // no threaded implementation for the moment
-    for ( LoadReqIt it = m_data->requests.begin();it != m_data->requests.end(); ++it) {
-        // force validation in debug builds
-        unsigned int pp = (*it).flags;
-        if ( m_data->validate ) {
-            pp |= aiProcess_ValidateDataStructure;
-        }
-
-        // setup config properties if necessary
-        ImporterPimpl* pimpl = m_data->pImporter->Pimpl();
-        pimpl->mFloatProperties  = (*it).map.floats;
-        pimpl->mIntProperties    = (*it).map.ints;
-        pimpl->mStringProperties = (*it).map.strings;
-        pimpl->mMatrixProperties = (*it).map.matrices;
-
-        if (!DefaultLogger::isNullLogger())
-        {
-            ASSIMP_LOG_INFO("%%% BEGIN EXTERNAL FILE %%%");
-            ASSIMP_LOG_INFO_F("File: ", (*it).file);
-        }
-        m_data->pImporter->ReadFile((*it).file,pp);
-        (*it).scene = m_data->pImporter->GetOrphanedScene();
-        (*it).loaded = true;
-
-        ASSIMP_LOG_INFO("%%% END EXTERNAL FILE %%%");
-    }
-}

+ 0 - 107
thirdparty/assimp/code/Common/BaseProcess.cpp

@@ -1,107 +0,0 @@
-/*
----------------------------------------------------------------------------
-Open Asset Import Library (assimp)
----------------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the following
-conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------------
-*/
-
-/** @file Implementation of BaseProcess */
-
-#include <assimp/BaseImporter.h>
-#include "BaseProcess.h"
-#include <assimp/DefaultLogger.hpp>
-#include <assimp/scene.h>
-#include "Importer.h"
-
-using namespace Assimp;
-
-// ------------------------------------------------------------------------------------------------
-// Constructor to be privately used by Importer
-BaseProcess::BaseProcess() AI_NO_EXCEPT
-: shared()
-, progress()
-{
-}
-
-// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
-BaseProcess::~BaseProcess()
-{
-    // nothing to do here
-}
-
-// ------------------------------------------------------------------------------------------------
-void BaseProcess::ExecuteOnScene( Importer* pImp)
-{
-    ai_assert(NULL != pImp && NULL != pImp->Pimpl()->mScene);
-
-    progress = pImp->GetProgressHandler();
-    ai_assert(progress);
-
-    SetupProperties( pImp );
-
-    // catch exceptions thrown inside the PostProcess-Step
-    try
-    {
-        Execute(pImp->Pimpl()->mScene);
-
-    } catch( const std::exception& err )    {
-
-        // extract error description
-        pImp->Pimpl()->mErrorString = err.what();
-        ASSIMP_LOG_ERROR(pImp->Pimpl()->mErrorString);
-
-        // and kill the partially imported data
-        delete pImp->Pimpl()->mScene;
-        pImp->Pimpl()->mScene = nullptr;
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-void BaseProcess::SetupProperties(const Importer* /*pImp*/)
-{
-    // the default implementation does nothing
-}
-
-// ------------------------------------------------------------------------------------------------
-bool BaseProcess::RequireVerboseFormat() const
-{
-    return true;
-}
-

+ 0 - 290
thirdparty/assimp/code/Common/BaseProcess.h

@@ -1,290 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file Base class of all import post processing steps */
-#ifndef INCLUDED_AI_BASEPROCESS_H
-#define INCLUDED_AI_BASEPROCESS_H
-
-#include <map>
-#include <assimp/GenericProperty.h>
-
-struct aiScene;
-
-namespace Assimp    {
-
-class Importer;
-
-// ---------------------------------------------------------------------------
-/** Helper class to allow post-processing steps to interact with each other.
- *
- *  The class maintains a simple property list that can be used by pp-steps
- *  to provide additional information to other steps. This is primarily
- *  intended for cross-step optimizations.
- */
-class SharedPostProcessInfo
-{
-public:
-
-    struct Base
-    {
-        virtual ~Base()
-        {}
-    };
-
-    //! Represents data that is allocated on the heap, thus needs to be deleted
-    template <typename T>
-    struct THeapData : public Base
-    {
-        explicit THeapData(T* in)
-            : data (in)
-        {}
-
-        ~THeapData()
-        {
-            delete data;
-        }
-        T* data;
-    };
-
-    //! Represents static, by-value data not allocated on the heap
-    template <typename T>
-    struct TStaticData : public Base
-    {
-        explicit TStaticData(T in)
-            : data (in)
-        {}
-
-        ~TStaticData()
-        {}
-
-        T data;
-    };
-
-    // some typedefs for cleaner code
-    typedef unsigned int KeyType;
-    typedef std::map<KeyType, Base*>  PropertyMap;
-
-public:
-
-    //! Destructor
-    ~SharedPostProcessInfo()
-    {
-        Clean();
-    }
-
-    //! Remove all stored properties from the table
-    void Clean()
-    {
-        // invoke the virtual destructor for all stored properties
-        for (PropertyMap::iterator it = pmap.begin(), end = pmap.end();
-             it != end; ++it)
-        {
-            delete (*it).second;
-        }
-        pmap.clear();
-    }
-
-    //! Add a heap property to the list
-    template <typename T>
-    void AddProperty( const char* name, T* in ){
-        AddProperty(name,(Base*)new THeapData<T>(in));
-    }
-
-    //! Add a static by-value property to the list
-    template <typename T>
-    void AddProperty( const char* name, T in ){
-        AddProperty(name,(Base*)new TStaticData<T>(in));
-    }
-
-
-    //! Get a heap property
-    template <typename T>
-    bool GetProperty( const char* name, T*& out ) const
-    {
-        THeapData<T>* t = (THeapData<T>*)GetPropertyInternal(name);
-        if(!t)
-        {
-            out = NULL;
-            return false;
-        }
-        out = t->data;
-        return true;
-    }
-
-    //! Get a static, by-value property
-    template <typename T>
-    bool GetProperty( const char* name, T& out ) const
-    {
-        TStaticData<T>* t = (TStaticData<T>*)GetPropertyInternal(name);
-        if(!t)return false;
-        out = t->data;
-        return true;
-    }
-
-    //! Remove a property of a specific type
-    void RemoveProperty( const char* name)  {
-        SetGenericPropertyPtr<Base>(pmap,name,NULL);
-    }
-
-private:
-
-    void AddProperty( const char* name, Base* data) {
-        SetGenericPropertyPtr<Base>(pmap,name,data);
-    }
-
-    Base* GetPropertyInternal( const char* name) const  {
-        return GetGenericProperty<Base*>(pmap,name,NULL);
-    }
-
-private:
-
-    //! Map of all stored properties
-    PropertyMap pmap;
-};
-
-#if 0
-
-// ---------------------------------------------------------------------------
-/** @brief Represents a dependency table for a postprocessing steps.
- *
- *  For future use.
- */
- struct PPDependencyTable
- {
-     unsigned int execute_me_before_these;
-     unsigned int execute_me_after_these;
-     unsigned int only_if_these_are_not_specified;
-     unsigned int mutually_exclusive_with;
- };
-
-#endif
-
-
-#define AI_SPP_SPATIAL_SORT "$Spat"
-
-// ---------------------------------------------------------------------------
-/** The BaseProcess defines a common interface for all post processing steps.
- * A post processing step is run after a successful import if the caller
- * specified the corresponding flag when calling ReadFile().
- * Enum #aiPostProcessSteps defines which flags are available.
- * After a successful import the Importer iterates over its internal array
- * of processes and calls IsActive() on each process to evaluate if the step
- * should be executed. If the function returns true, the class' Execute()
- * function is called subsequently.
- */
-class ASSIMP_API_WINONLY BaseProcess {
-    friend class Importer;
-
-public:
-    /** Constructor to be privately used by Importer */
-    BaseProcess() AI_NO_EXCEPT;
-
-    /** Destructor, private as well */
-    virtual ~BaseProcess();
-
-    // -------------------------------------------------------------------
-    /** Returns whether the processing step is present in the given flag.
-     * @param pFlags The processing flags the importer was called with. A
-     *   bitwise combination of #aiPostProcessSteps.
-     * @return true if the process is present in this flag fields,
-     *   false if not.
-    */
-    virtual bool IsActive( unsigned int pFlags) const = 0;
-
-    // -------------------------------------------------------------------
-    /** Check whether this step expects its input vertex data to be
-     *  in verbose format. */
-    virtual bool RequireVerboseFormat() const;
-
-    // -------------------------------------------------------------------
-    /** Executes the post processing step on the given imported data.
-    * The function deletes the scene if the postprocess step fails (
-    * the object pointer will be set to NULL).
-    * @param pImp Importer instance (pImp->mScene must be valid)
-    */
-    void ExecuteOnScene( Importer* pImp);
-
-    // -------------------------------------------------------------------
-    /** Called prior to ExecuteOnScene().
-    * The function is a request to the process to update its configuration
-    * basing on the Importer's configuration property list.
-    */
-    virtual void SetupProperties(const Importer* pImp);
-
-    // -------------------------------------------------------------------
-    /** Executes the post processing step on the given imported data.
-    * A process should throw an ImportErrorException* if it fails.
-    * This method must be implemented by deriving classes.
-    * @param pScene The imported data to work at.
-    */
-    virtual void Execute( aiScene* pScene) = 0;
-
-
-    // -------------------------------------------------------------------
-    /** Assign a new SharedPostProcessInfo to the step. This object
-     *  allows multiple postprocess steps to share data.
-     * @param sh May be NULL
-    */
-    inline void SetSharedData(SharedPostProcessInfo* sh)    {
-        shared = sh;
-    }
-
-    // -------------------------------------------------------------------
-    /** Get the shared data that is assigned to the step.
-    */
-    inline SharedPostProcessInfo* GetSharedData()   {
-        return shared;
-    }
-
-protected:
-
-    /** See the doc of #SharedPostProcessInfo for more details */
-    SharedPostProcessInfo* shared;
-
-    /** Currently active progress handler */
-    ProgressHandler* progress;
-};
-
-
-} // end of namespace Assimp
-
-#endif // AI_BASEPROCESS_H_INC

+ 0 - 155
thirdparty/assimp/code/Common/Bitmap.cpp

@@ -1,155 +0,0 @@
-/*
----------------------------------------------------------------------------
-Open Asset Import Library (assimp)
----------------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the following
-conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------------
-*/
-
-/** @file Bitmap.cpp
- *  @brief Defines bitmap format helper for textures
- *
- * Used for file formats which embed their textures into the model file.
- */
-
-
-#include <assimp/Bitmap.h>
-#include <assimp/texture.h>
-#include <assimp/IOStream.hpp>
-#include <assimp/ByteSwapper.h>
-
-namespace Assimp {
-
-    void Bitmap::Save(aiTexture* texture, IOStream* file) {
-        if(file != NULL) {
-            Header header;
-            DIB dib;
-
-            dib.size = DIB::dib_size;
-            dib.width = texture->mWidth;
-            dib.height = texture->mHeight;
-            dib.planes = 1;
-            dib.bits_per_pixel = 8 * mBytesPerPixel;
-            dib.compression = 0;
-            dib.image_size = (((dib.width * mBytesPerPixel) + 3) & 0x0000FFFC) * dib.height;
-            dib.x_resolution = 0;
-            dib.y_resolution = 0;
-            dib.nb_colors = 0;
-            dib.nb_important_colors = 0;
-
-            header.type = 0x4D42; // 'BM'
-            header.offset = Header::header_size + DIB::dib_size;
-            header.size = header.offset + dib.image_size;
-            header.reserved1 = 0;
-            header.reserved2 = 0;
-
-            WriteHeader(header, file);
-            WriteDIB(dib, file);
-            WriteData(texture, file);
-        }
-    }
-
-    template<typename T>
-    inline 
-    std::size_t Copy(uint8_t* data, const T &field) {
-#ifdef AI_BUILD_BIG_ENDIAN
-        T field_swapped=AI_BE(field);
-        std::memcpy(data, &field_swapped, sizeof(field)); return sizeof(field);
-#else
-        std::memcpy(data, &AI_BE(field), sizeof(field)); return sizeof(field);
-#endif
-    }
-
-    void Bitmap::WriteHeader(Header& header, IOStream* file) {
-        uint8_t data[Header::header_size];
-
-        std::size_t offset = 0;
-
-        offset += Copy(&data[offset], header.type);
-        offset += Copy(&data[offset], header.size);
-        offset += Copy(&data[offset], header.reserved1);
-        offset += Copy(&data[offset], header.reserved2);
-                  Copy(&data[offset], header.offset);
-
-        file->Write(data, Header::header_size, 1);
-    }
-
-    void Bitmap::WriteDIB(DIB& dib, IOStream* file) {
-        uint8_t data[DIB::dib_size];
-
-        std::size_t offset = 0;
-
-        offset += Copy(&data[offset], dib.size);
-        offset += Copy(&data[offset], dib.width);
-        offset += Copy(&data[offset], dib.height);
-        offset += Copy(&data[offset], dib.planes);
-        offset += Copy(&data[offset], dib.bits_per_pixel);
-        offset += Copy(&data[offset], dib.compression);
-        offset += Copy(&data[offset], dib.image_size);
-        offset += Copy(&data[offset], dib.x_resolution);
-        offset += Copy(&data[offset], dib.y_resolution);
-        offset += Copy(&data[offset], dib.nb_colors);
-                  Copy(&data[offset], dib.nb_important_colors);
-
-        file->Write(data, DIB::dib_size, 1);
-    }
-
-    void Bitmap::WriteData(aiTexture* texture, IOStream* file) {
-        static const std::size_t padding_offset = 4;
-        static const uint8_t padding_data[padding_offset] = {0x0, 0x0, 0x0, 0x0};
-
-        unsigned int padding = (padding_offset - ((mBytesPerPixel * texture->mWidth) % padding_offset)) % padding_offset;
-        uint8_t pixel[mBytesPerPixel];
-
-        for(std::size_t i = 0; i < texture->mHeight; ++i) {
-            for(std::size_t j = 0; j < texture->mWidth; ++j) {
-                const aiTexel& texel = texture->pcData[(texture->mHeight - i - 1) * texture->mWidth + j]; // Bitmap files are stored in bottom-up format
-
-                pixel[0] = texel.r;
-                pixel[1] = texel.g;
-                pixel[2] = texel.b;
-                pixel[3] = texel.a;
-
-                file->Write(pixel, mBytesPerPixel, 1);
-            }
-
-            file->Write(padding_data, padding, 1);
-        }
-    }
-
-}

+ 0 - 88
thirdparty/assimp/code/Common/CreateAnimMesh.cpp

@@ -1,88 +0,0 @@
-/*
----------------------------------------------------------------------------
-Open Asset Import Library (assimp)
----------------------------------------------------------------------------
-
-Copyright (C) 2016 The Qt Company Ltd.
-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 <assimp/CreateAnimMesh.h>
-
-namespace Assimp    {
-
-aiAnimMesh *aiCreateAnimMesh(const aiMesh *mesh)
-{
-    aiAnimMesh *animesh = new aiAnimMesh;
-    animesh->mNumVertices = mesh->mNumVertices;
-    if (mesh->mVertices) {
-        animesh->mVertices = new aiVector3D[animesh->mNumVertices];
-        std::memcpy(animesh->mVertices, mesh->mVertices, mesh->mNumVertices * sizeof(aiVector3D));
-    }
-    if (mesh->mNormals) {
-        animesh->mNormals = new aiVector3D[animesh->mNumVertices];
-        std::memcpy(animesh->mNormals, mesh->mNormals, mesh->mNumVertices * sizeof(aiVector3D));
-    }
-    if (mesh->mTangents) {
-        animesh->mTangents = new aiVector3D[animesh->mNumVertices];
-        std::memcpy(animesh->mTangents, mesh->mTangents, mesh->mNumVertices * sizeof(aiVector3D));
-    }
-    if (mesh->mBitangents) {
-        animesh->mBitangents = new aiVector3D[animesh->mNumVertices];
-        std::memcpy(animesh->mBitangents, mesh->mBitangents, mesh->mNumVertices * sizeof(aiVector3D));
-    }
-
-    for (int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) {
-        if (mesh->mColors[i]) {
-            animesh->mColors[i] = new aiColor4D[animesh->mNumVertices];
-            std::memcpy(animesh->mColors[i], mesh->mColors[i], mesh->mNumVertices * sizeof(aiColor4D));
-        } else {
-            animesh->mColors[i] = NULL;
-        }
-    }
-
-    for (int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
-        if (mesh->mTextureCoords[i]) {
-            animesh->mTextureCoords[i] = new aiVector3D[animesh->mNumVertices];
-            std::memcpy(animesh->mTextureCoords[i], mesh->mTextureCoords[i], mesh->mNumVertices * sizeof(aiVector3D));
-        } else {
-            animesh->mTextureCoords[i] = NULL;
-        }
-    }
-    return animesh;
-}
-
-} // end of namespace Assimp

+ 0 - 154
thirdparty/assimp/code/Common/DefaultIOStream.cpp

@@ -1,154 +0,0 @@
-/*
----------------------------------------------------------------------------
-Open Asset Import Library (assimp)
----------------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the following
-conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------------
-*/
-/** @file  DefaultIOStream.cpp
- *  @brief Default File I/O implementation for #Importer
- */
-
-
-#include <assimp/ai_assert.h>
-#include <assimp/DefaultIOStream.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-using namespace Assimp;
-
-// ----------------------------------------------------------------------------------
-DefaultIOStream::~DefaultIOStream()
-{
-    if (mFile) {
-        ::fclose(mFile);
-        mFile = nullptr;
-    }
-}
-
-// ----------------------------------------------------------------------------------
-size_t DefaultIOStream::Read(void* pvBuffer,
-    size_t pSize,
-    size_t pCount)
-{
-    ai_assert(NULL != pvBuffer && 0 != pSize && 0 != pCount);
-    return (mFile ? ::fread(pvBuffer, pSize, pCount, mFile) : 0);
-}
-
-// ----------------------------------------------------------------------------------
-size_t DefaultIOStream::Write(const void* pvBuffer,
-    size_t pSize,
-    size_t pCount)
-{
-    ai_assert(NULL != pvBuffer && 0 != pSize && 0 != pCount);
-    return (mFile ? ::fwrite(pvBuffer, pSize, pCount, mFile) : 0);
-}
-
-// ----------------------------------------------------------------------------------
-aiReturn DefaultIOStream::Seek(size_t pOffset,
-     aiOrigin pOrigin)
-{
-    if (!mFile) {
-        return AI_FAILURE;
-    }
-
-    // Just to check whether our enum maps one to one with the CRT constants
-    static_assert(aiOrigin_CUR == SEEK_CUR &&
-        aiOrigin_END == SEEK_END && aiOrigin_SET == SEEK_SET, "aiOrigin_CUR == SEEK_CUR && \
-        aiOrigin_END == SEEK_END && aiOrigin_SET == SEEK_SET");
-
-    // do the seek
-    return (0 == ::fseek(mFile, (long)pOffset,(int)pOrigin) ? AI_SUCCESS : AI_FAILURE);
-}
-
-// ----------------------------------------------------------------------------------
-size_t DefaultIOStream::Tell() const
-{
-    if (!mFile) {
-        return 0;
-    }
-    return ::ftell(mFile);
-}
-
-// ----------------------------------------------------------------------------------
-size_t DefaultIOStream::FileSize() const
-{
-    if (! mFile || mFilename.empty()) {
-        return 0;
-    }
-
-    if (SIZE_MAX == mCachedSize ) {
-
-        // Although fseek/ftell would allow us to reuse the existing file handle here,
-        // it is generally unsafe because:
-        //  - For binary streams, it is not technically well-defined
-        //  - For text files the results are meaningless
-        // That's why we use the safer variant fstat here.
-        //
-        // See here for details:
-        // https://www.securecoding.cert.org/confluence/display/seccode/FIO19-C.+Do+not+use+fseek()+and+ftell()+to+compute+the+size+of+a+regular+file
-#if defined _WIN32 && (!defined __GNUC__ || __MSVCRT_VERSION__ >= 0x0601)
-        struct __stat64 fileStat;
-        //using fileno + fstat avoids having to handle the filename
-        int err = _fstat64(  _fileno(mFile), &fileStat );
-        if (0 != err)
-            return 0;
-        mCachedSize = (size_t) (fileStat.st_size);
-#elif defined __GNUC__ || defined __APPLE__ || defined __MACH__ || defined __FreeBSD__
-        struct stat fileStat;
-        int err = stat(mFilename.c_str(), &fileStat );
-        if (0 != err)
-            return 0;
-        const unsigned long long cachedSize = fileStat.st_size;
-        mCachedSize = static_cast< size_t >( cachedSize );
-#else
-#   error "Unknown platform"
-#endif
-    }
-    return mCachedSize;
-}
-
-// ----------------------------------------------------------------------------------
-void DefaultIOStream::Flush()
-{
-    if (mFile) {
-        ::fflush(mFile);
-    }
-}
-
-// ----------------------------------------------------------------------------------

+ 0 - 216
thirdparty/assimp/code/Common/DefaultIOSystem.cpp

@@ -1,216 +0,0 @@
-/*
----------------------------------------------------------------------------
-Open Asset Import Library (assimp)
----------------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the following
-conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------------
-*/
-/** @file Default implementation of IOSystem using the standard C file functions */
-
-#include <assimp/StringComparison.h>
-
-#include <assimp/DefaultIOSystem.h>
-#include <assimp/DefaultIOStream.h>
-#include <assimp/DefaultLogger.hpp>
-#include <assimp/ai_assert.h>
-#include <stdlib.h>
-
-#ifdef __unix__
-#include <sys/param.h>
-#include <stdlib.h>
-#endif
-
-#ifdef _WIN32
-#include <windows.h>
-#endif
-
-using namespace Assimp;
-
-#ifdef _WIN32
-static std::wstring Utf8ToWide(const char* in)
-{
-    int size = MultiByteToWideChar(CP_UTF8, 0, in, -1, nullptr, 0);
-    // size includes terminating null; std::wstring adds null automatically
-    std::wstring out(static_cast<size_t>(size) - 1, L'\0');
-    MultiByteToWideChar(CP_UTF8, 0, in, -1, &out[0], size);
-    return out;
-}
-
-static std::string WideToUtf8(const wchar_t* in)
-{
-    int size = WideCharToMultiByte(CP_UTF8, 0, in, -1, nullptr, 0, nullptr, nullptr);
-    // size includes terminating null; std::string adds null automatically
-    std::string out(static_cast<size_t>(size) - 1, '\0');
-    WideCharToMultiByte(CP_UTF8, 0, in, -1, &out[0], size, nullptr, nullptr);
-    return out;
-}
-#endif
-
-// ------------------------------------------------------------------------------------------------
-// Tests for the existence of a file at the given path.
-bool DefaultIOSystem::Exists(const char* pFile) const
-{
-#ifdef _WIN32
-    struct __stat64 filestat;
-    if (_wstat64(Utf8ToWide(pFile).c_str(), &filestat) != 0) {
-        return false;
-    }
-#else
-    FILE* file = ::fopen(pFile, "rb");
-    if (!file)
-        return false;
-
-    ::fclose(file);
-#endif
-    return true;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Open a new file with a given path.
-IOStream* DefaultIOSystem::Open(const char* strFile, const char* strMode)
-{
-    ai_assert(strFile != nullptr);
-    ai_assert(strMode != nullptr);
-    FILE* file;
-#ifdef _WIN32
-    file = ::_wfopen(Utf8ToWide(strFile).c_str(), Utf8ToWide(strMode).c_str());
-#else
-    file = ::fopen(strFile, strMode);
-#endif
-    if (!file)
-        return nullptr;
-
-    return new DefaultIOStream(file, strFile);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Closes the given file and releases all resources associated with it.
-void DefaultIOSystem::Close(IOStream* pFile)
-{
-    delete pFile;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Returns the operation specific directory separator
-char DefaultIOSystem::getOsSeparator() const
-{
-#ifndef _WIN32
-    return '/';
-#else
-    return '\\';
-#endif
-}
-
-// ------------------------------------------------------------------------------------------------
-// IOSystem default implementation (ComparePaths isn't a pure virtual function)
-bool IOSystem::ComparePaths(const char* one, const char* second) const
-{
-    return !ASSIMP_stricmp(one, second);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Convert a relative path into an absolute path
-inline static std::string MakeAbsolutePath(const char* in)
-{
-    ai_assert(in);
-    std::string out;
-#ifdef _WIN32
-    wchar_t* ret = ::_wfullpath(nullptr, Utf8ToWide(in).c_str(), 0);
-    if (ret) {
-        out = WideToUtf8(ret);
-        free(ret);
-    }
-#else
-    char* ret = realpath(in, nullptr);
-    if (ret) {
-        out = ret;
-        free(ret);
-    }
-#endif
-    if (!ret) {
-        // preserve the input path, maybe someone else is able to fix
-        // the path before it is accessed (e.g. our file system filter)
-        ASSIMP_LOG_WARN_F("Invalid path: ", std::string(in));
-        out = in;
-    }
-    return out;
-}
-
-// ------------------------------------------------------------------------------------------------
-// DefaultIOSystem's more specialized implementation
-bool DefaultIOSystem::ComparePaths(const char* one, const char* second) const
-{
-    // chances are quite good both paths are formatted identically,
-    // so we can hopefully return here already
-    if (!ASSIMP_stricmp(one, second))
-        return true;
-
-    std::string temp1 = MakeAbsolutePath(one);
-    std::string temp2 = MakeAbsolutePath(second);
-
-    return !ASSIMP_stricmp(temp1, temp2);
-}
-
-// ------------------------------------------------------------------------------------------------
-std::string DefaultIOSystem::fileName(const std::string& path)
-{
-    std::string ret = path;
-    std::size_t last = ret.find_last_of("\\/");
-    if (last != std::string::npos) ret = ret.substr(last + 1);
-    return ret;
-}
-
-// ------------------------------------------------------------------------------------------------
-std::string DefaultIOSystem::completeBaseName(const std::string& path)
-{
-    std::string ret = fileName(path);
-    std::size_t pos = ret.find_last_of('.');
-    if (pos != std::string::npos) ret = ret.substr(0, pos);
-    return ret;
-}
-
-// ------------------------------------------------------------------------------------------------
-std::string DefaultIOSystem::absolutePath(const std::string& path)
-{
-    std::string ret = path;
-    std::size_t last = ret.find_last_of("\\/");
-    if (last != std::string::npos) ret = ret.substr(0, last);
-    return ret;
-}
-
-// ------------------------------------------------------------------------------------------------

+ 0 - 418
thirdparty/assimp/code/Common/DefaultLogger.cpp

@@ -1,418 +0,0 @@
-/*
----------------------------------------------------------------------------
-Open Asset Import Library (assimp)
----------------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the following
-conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------------
-*/
-
-/** @file  DefaultLogger.cpp
- *  @brief Implementation of DefaultLogger (and Logger)
- */
-
-// Default log streams
-#include "Win32DebugLogStream.h"
-#include "StdOStreamLogStream.h"
-#include "FileLogStream.h"
-#include <assimp/StringUtils.h>
-
-#include <assimp/DefaultIOSystem.h>
-#include <assimp/NullLogger.hpp>
-#include <assimp/DefaultLogger.hpp>
-#include <assimp/ai_assert.h>
-#include <iostream>
-#include <stdio.h>
-
-#ifndef ASSIMP_BUILD_SINGLETHREADED
-#   include <thread>
-#   include <mutex>
-    std::mutex loggerMutex;
-#endif
-
-namespace Assimp    {
-
-// ----------------------------------------------------------------------------------
-NullLogger DefaultLogger::s_pNullLogger;
-Logger *DefaultLogger::m_pLogger = &DefaultLogger::s_pNullLogger;
-
-static const unsigned int SeverityAll = Logger::Info | Logger::Err | Logger::Warn | Logger::Debugging;
-
-// ----------------------------------------------------------------------------------
-// Represents a log-stream + its error severity
-struct LogStreamInfo {
-    unsigned int  m_uiErrorSeverity;
-    LogStream    *m_pStream;
-
-    // Constructor
-    LogStreamInfo( unsigned int uiErrorSev, LogStream *pStream ) :
-        m_uiErrorSeverity( uiErrorSev ),
-        m_pStream( pStream ) {
-        // empty
-    }
-
-    // Destructor
-    ~LogStreamInfo() {
-        delete m_pStream;
-    }
-};
-
-// ----------------------------------------------------------------------------------
-// Construct a default log stream
-LogStream* LogStream::createDefaultStream(aiDefaultLogStream    streams,
-    const char* name /*= "AssimpLog.txt"*/,
-    IOSystem* io            /*= NULL*/)
-{
-    switch (streams)
-    {
-        // This is a platform-specific feature
-    case aiDefaultLogStream_DEBUGGER:
-#ifdef WIN32
-        return new Win32DebugLogStream();
-#else
-        return nullptr;
-#endif
-
-        // Platform-independent default streams
-    case aiDefaultLogStream_STDERR:
-        return new StdOStreamLogStream(std::cerr);
-    case aiDefaultLogStream_STDOUT:
-        return new StdOStreamLogStream(std::cout);
-    case aiDefaultLogStream_FILE:
-        return (name && *name ? new FileLogStream(name,io) : nullptr );
-    default:
-        // We don't know this default log stream, so raise an assertion
-        ai_assert(false);
-
-    };
-
-    // For compilers without dead code path detection
-    return NULL;
-}
-
-// ----------------------------------------------------------------------------------
-//  Creates the only singleton instance
-Logger *DefaultLogger::create(const char* name /*= "AssimpLog.txt"*/,
-    LogSeverity severity                       /*= NORMAL*/,
-    unsigned int defStreams                    /*= aiDefaultLogStream_DEBUGGER | aiDefaultLogStream_FILE*/,
-    IOSystem* io                               /*= NULL*/) {
-    // enter the mutex here to avoid concurrency problems
-#ifndef ASSIMP_BUILD_SINGLETHREADED
-    std::lock_guard<std::mutex> lock(loggerMutex);
-#endif
-
-    if ( m_pLogger && !isNullLogger() ) {
-        delete m_pLogger;
-    }
-
-    m_pLogger = new DefaultLogger( severity );
-
-    // Attach default log streams
-    // Stream the log to the MSVC debugger?
-    if ( defStreams & aiDefaultLogStream_DEBUGGER ) {
-        m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_DEBUGGER ) );
-    }
-
-    // Stream the log to COUT?
-    if ( defStreams & aiDefaultLogStream_STDOUT ) {
-        m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_STDOUT ) );
-    }
-
-    // Stream the log to CERR?
-    if ( defStreams & aiDefaultLogStream_STDERR ) {
-        m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_STDERR ) );
-    }
-
-    // Stream the log to a file
-    if ( defStreams & aiDefaultLogStream_FILE && name && *name ) {
-        m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_FILE, name, io ) );
-    }
-
-    return m_pLogger;
-}
-
-// ----------------------------------------------------------------------------------
-void Logger::debug(const char* message) {
-
-    // SECURITY FIX: otherwise it's easy to produce overruns since
-    // sometimes importers will include data from the input file
-    // (i.e. node names) in their messages.
-    if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) {
-        return;
-    }
-    return OnDebug(message);
-}
-
-// ----------------------------------------------------------------------------------
-void Logger::info(const char* message)  {
-
-    // SECURITY FIX: see above
-    if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) {
-        return;
-    }
-    return OnInfo(message);
-}
-
-// ----------------------------------------------------------------------------------
-void Logger::warn(const char* message)  {
-
-    // SECURITY FIX: see above
-    if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) {
-        return;
-    }
-    return OnWarn(message);
-}
-
-// ----------------------------------------------------------------------------------
-void Logger::error(const char* message) {
-    // SECURITY FIX: see above
-    if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) {
-        return;
-    }
-    return OnError(message);
-}
-
-// ----------------------------------------------------------------------------------
-void DefaultLogger::set( Logger *logger ) {
-    // enter the mutex here to avoid concurrency problems
-#ifndef ASSIMP_BUILD_SINGLETHREADED
-    std::lock_guard<std::mutex> lock(loggerMutex);
-#endif
-
-    if ( nullptr == logger ) {
-        logger = &s_pNullLogger;
-    }
-    if ( nullptr != m_pLogger && !isNullLogger() ) {
-        delete m_pLogger;
-    }
-
-    DefaultLogger::m_pLogger = logger;
-}
-
-// ----------------------------------------------------------------------------------
-bool DefaultLogger::isNullLogger() {
-    return m_pLogger == &s_pNullLogger;
-}
-
-// ----------------------------------------------------------------------------------
-Logger *DefaultLogger::get() {
-    return m_pLogger;
-}
-
-// ----------------------------------------------------------------------------------
-//  Kills the only instance
-void DefaultLogger::kill() {
-    // enter the mutex here to avoid concurrency problems
-#ifndef ASSIMP_BUILD_SINGLETHREADED
-    std::lock_guard<std::mutex> lock(loggerMutex);
-#endif
-
-	if ( m_pLogger == &s_pNullLogger ) {
-		return;
-	}
-    delete m_pLogger;
-    m_pLogger = &s_pNullLogger;
-}
-
-// ----------------------------------------------------------------------------------
-//  Debug message
-void DefaultLogger::OnDebug( const char* message ) {
-    if ( m_Severity == Logger::NORMAL ) {
-        return;
-    }
-
-	static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
-	char msg[Size];
-	ai_snprintf(msg, Size, "Debug, T%u: %s", GetThreadID(), message);
-
-    WriteToStreams( msg, Logger::Debugging );
-}
-
-// ----------------------------------------------------------------------------------
-//  Logs an info
-void DefaultLogger::OnInfo( const char* message ){
-	static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
-	char msg[Size];
-    ai_snprintf(msg, Size, "Info,  T%u: %s", GetThreadID(), message );
-
-    WriteToStreams( msg , Logger::Info );
-}
-
-// ----------------------------------------------------------------------------------
-//  Logs a warning
-void DefaultLogger::OnWarn( const char* message ) {
-	static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
-	char msg[Size];
-	ai_snprintf(msg, Size, "Warn,  T%u: %s", GetThreadID(), message );
-
-    WriteToStreams( msg, Logger::Warn );
-}
-
-// ----------------------------------------------------------------------------------
-//  Logs an error
-void DefaultLogger::OnError( const char* message ) {
-	static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
-	char msg[ Size ];
-    ai_snprintf(msg, Size, "Error, T%u: %s", GetThreadID(), message );
-
-    WriteToStreams( msg, Logger::Err );
-}
-
-// ----------------------------------------------------------------------------------
-//  Will attach a new stream
-bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity ) {
-    if ( nullptr == pStream ) {
-        return false;
-    }
-
-    if (0 == severity)  {
-        severity = Logger::Info | Logger::Err | Logger::Warn | Logger::Debugging;
-    }
-
-    for ( StreamIt it = m_StreamArray.begin();
-        it != m_StreamArray.end();
-        ++it )
-    {
-        if ( (*it)->m_pStream == pStream ) {
-            (*it)->m_uiErrorSeverity |= severity;
-            return true;
-        }
-    }
-
-    LogStreamInfo *pInfo = new LogStreamInfo( severity, pStream );
-    m_StreamArray.push_back( pInfo );
-    return true;
-}
-
-// ----------------------------------------------------------------------------------
-//  Detach a stream
-bool DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity ) {
-    if ( nullptr == pStream ) {
-        return false;
-    }
-
-    if (0 == severity)  {
-        severity = SeverityAll;
-    }
-
-    bool res( false );
-    for ( StreamIt it = m_StreamArray.begin(); it != m_StreamArray.end(); ++it ) {
-        if ( (*it)->m_pStream == pStream ) {
-            (*it)->m_uiErrorSeverity &= ~severity;
-            if ( (*it)->m_uiErrorSeverity == 0 ) {
-                // don't delete the underlying stream 'cause the caller gains ownership again
-                (**it).m_pStream = nullptr;
-                delete *it;
-                m_StreamArray.erase( it );
-                res = true;
-                break;
-            }
-            return true;
-        }
-    }
-    return res;
-}
-
-// ----------------------------------------------------------------------------------
-//  Constructor
-DefaultLogger::DefaultLogger(LogSeverity severity)
-    :   Logger  ( severity )
-    ,   noRepeatMsg (false)
-    ,   lastLen( 0 ) {
-    lastMsg[0] = '\0';
-}
-
-// ----------------------------------------------------------------------------------
-//  Destructor
-DefaultLogger::~DefaultLogger() {
-    for ( StreamIt it = m_StreamArray.begin(); it != m_StreamArray.end(); ++it ) {
-        // also frees the underlying stream, we are its owner.
-        delete *it;
-    }
-}
-
-// ----------------------------------------------------------------------------------
-//  Writes message to stream
-void DefaultLogger::WriteToStreams(const char *message, ErrorSeverity ErrorSev ) {
-    ai_assert(nullptr != message);
-
-    // Check whether this is a repeated message
-    if (! ::strncmp( message,lastMsg, lastLen-1))
-    {
-        if (!noRepeatMsg)
-        {
-            noRepeatMsg = true;
-            message = "Skipping one or more lines with the same contents\n";
-        }
-        else return;
-    }
-    else
-    {
-        // append a new-line character to the message to be printed
-        lastLen = ::strlen(message);
-        ::memcpy(lastMsg,message,lastLen+1);
-        ::strcat(lastMsg+lastLen,"\n");
-
-        message = lastMsg;
-        noRepeatMsg = false;
-        ++lastLen;
-    }
-    for ( ConstStreamIt it = m_StreamArray.begin();
-        it != m_StreamArray.end();
-        ++it)
-    {
-        if ( ErrorSev & (*it)->m_uiErrorSeverity )
-            (*it)->m_pStream->write( message);
-    }
-}
-
-// ----------------------------------------------------------------------------------
-//  Returns thread id, if not supported only a zero will be returned.
-unsigned int DefaultLogger::GetThreadID()
-{
-    // fixme: we can get this value via std::threads
-    // std::this_thread::get_id().hash() returns a (big) size_t, not sure if this is useful in this case.
-#ifdef WIN32
-    return (unsigned int)::GetCurrentThreadId();
-#else
-    return 0; // not supported
-#endif
-}
-
-// ----------------------------------------------------------------------------------
-
-} // !namespace Assimp

+ 0 - 65
thirdparty/assimp/code/Common/DefaultProgressHandler.h

@@ -1,65 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file ProgressHandler.hpp
- *  @brief Abstract base class 'ProgressHandler'.
- */
-#ifndef INCLUDED_AI_DEFAULTPROGRESSHANDLER_H
-#define INCLUDED_AI_DEFAULTPROGRESSHANDLER_H
-
-#include <assimp/ProgressHandler.hpp>
-
-namespace Assimp    {
-
-// ------------------------------------------------------------------------------------
-/** @brief Internal default implementation of the #ProgressHandler interface. */
-class DefaultProgressHandler : public ProgressHandler    {
-
-    virtual bool Update(float /*percentage*/) {
-        return false;
-    }
-
-
-}; // !class DefaultProgressHandler
-} // Namespace Assimp
-
-#endif

+ 0 - 636
thirdparty/assimp/code/Common/Exporter.cpp

@@ -1,636 +0,0 @@
-/*
----------------------------------------------------------------------------
-Open Asset Import Library (assimp)
----------------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the following
-conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------------
-*/
-
-/** @file Exporter.cpp
-
-Assimp export interface. While it's public interface bears many similarities
-to the import interface (in fact, it is largely symmetric), the internal
-implementations differs a lot. Exporters are considered stateless and are
-simple callbacks which we maintain in a global list along with their
-description strings.
-
-Here we implement only the C++ interface (Assimp::Exporter).
-*/
-
-#ifndef ASSIMP_BUILD_NO_EXPORT
-
-#include <assimp/BlobIOSystem.h>
-#include <assimp/SceneCombiner.h>
-#include <assimp/DefaultIOSystem.h>
-#include <assimp/Exporter.hpp>
-#include <assimp/mesh.h>
-#include <assimp/postprocess.h>
-#include <assimp/scene.h>
-#include <assimp/Exceptional.h>
-
-#include "Common/DefaultProgressHandler.h"
-#include "Common/BaseProcess.h"
-#include "Common/ScenePrivate.h"
-#include "PostProcessing/CalcTangentsProcess.h"
-#include "PostProcessing/MakeVerboseFormat.h"
-#include "PostProcessing/JoinVerticesProcess.h"
-#include "PostProcessing/ConvertToLHProcess.h"
-#include "PostProcessing/PretransformVertices.h"
-
-#include <memory>
-
-namespace Assimp {
-
-// PostStepRegistry.cpp
-void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out);
-
-// ------------------------------------------------------------------------------------------------
-// Exporter worker function prototypes. Should not be necessary to #ifndef them, it's just a prototype
-// do not use const, because some exporter need to convert the scene temporary
-void ExportSceneCollada(const char*,IOSystem*, const aiScene*, const ExportProperties*);
-void ExportSceneXFile(const char*,IOSystem*, const aiScene*, const ExportProperties*);
-void ExportSceneStep(const char*,IOSystem*, const aiScene*, const ExportProperties*);
-void ExportSceneObj(const char*,IOSystem*, const aiScene*, const ExportProperties*);
-void ExportSceneObjNoMtl(const char*,IOSystem*, const aiScene*, const ExportProperties*);
-void ExportSceneSTL(const char*,IOSystem*, const aiScene*, const ExportProperties*);
-void ExportSceneSTLBinary(const char*,IOSystem*, const aiScene*, const ExportProperties*);
-void ExportScenePly(const char*,IOSystem*, const aiScene*, const ExportProperties*);
-void ExportScenePlyBinary(const char*, IOSystem*, const aiScene*, const ExportProperties*);
-void ExportScene3DS(const char*, IOSystem*, const aiScene*, const ExportProperties*);
-void ExportSceneGLTF(const char*, IOSystem*, const aiScene*, const ExportProperties*);
-void ExportSceneGLB(const char*, IOSystem*, const aiScene*, const ExportProperties*);
-void ExportSceneGLTF2(const char*, IOSystem*, const aiScene*, const ExportProperties*);
-void ExportSceneGLB2(const char*, IOSystem*, const aiScene*, const ExportProperties*);
-void ExportSceneAssbin(const char*, IOSystem*, const aiScene*, const ExportProperties*);
-void ExportSceneAssxml(const char*, IOSystem*, const aiScene*, const ExportProperties*);
-void ExportSceneX3D(const char*, IOSystem*, const aiScene*, const ExportProperties*);
-void ExportSceneFBX(const char*, IOSystem*, const aiScene*, const ExportProperties*);
-void ExportSceneFBXA(const char*, IOSystem*, const aiScene*, const ExportProperties*);
-void ExportScene3MF( const char*, IOSystem*, const aiScene*, const ExportProperties* );
-void ExportSceneM3D(const char*, IOSystem*, const aiScene*, const ExportProperties*);
-void ExportSceneA3D(const char*, IOSystem*, const aiScene*, const ExportProperties*);
-void ExportAssimp2Json(const char* , IOSystem*, const aiScene* , const Assimp::ExportProperties*);
-
-// ------------------------------------------------------------------------------------------------
-// global array of all export formats which Assimp supports in its current build
-Exporter::ExportFormatEntry gExporters[] =
-{
-#ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER
-    Exporter::ExportFormatEntry( "collada", "COLLADA - Digital Asset Exchange Schema", "dae", &ExportSceneCollada ),
-#endif
-
-#ifndef ASSIMP_BUILD_NO_X_EXPORTER
-    Exporter::ExportFormatEntry( "x", "X Files", "x", &ExportSceneXFile,
-        aiProcess_MakeLeftHanded | aiProcess_FlipWindingOrder | aiProcess_FlipUVs ),
-#endif
-
-#ifndef ASSIMP_BUILD_NO_STEP_EXPORTER
-    Exporter::ExportFormatEntry( "stp", "Step Files", "stp", &ExportSceneStep, 0 ),
-#endif
-
-#ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER
-    Exporter::ExportFormatEntry( "obj", "Wavefront OBJ format", "obj", &ExportSceneObj,
-        aiProcess_GenSmoothNormals /*| aiProcess_PreTransformVertices */ ),
-    Exporter::ExportFormatEntry( "objnomtl", "Wavefront OBJ format without material file", "obj", &ExportSceneObjNoMtl,
-        aiProcess_GenSmoothNormals /*| aiProcess_PreTransformVertices */ ),
-#endif
-
-#ifndef ASSIMP_BUILD_NO_STL_EXPORTER
-    Exporter::ExportFormatEntry( "stl", "Stereolithography", "stl" , &ExportSceneSTL,
-        aiProcess_Triangulate | aiProcess_GenNormals | aiProcess_PreTransformVertices
-    ),
-    Exporter::ExportFormatEntry( "stlb", "Stereolithography (binary)", "stl" , &ExportSceneSTLBinary,
-        aiProcess_Triangulate | aiProcess_GenNormals | aiProcess_PreTransformVertices
-    ),
-#endif
-
-#ifndef ASSIMP_BUILD_NO_PLY_EXPORTER
-    Exporter::ExportFormatEntry( "ply", "Stanford Polygon Library", "ply" , &ExportScenePly,
-        aiProcess_PreTransformVertices
-    ),
-    Exporter::ExportFormatEntry( "plyb", "Stanford Polygon Library (binary)", "ply", &ExportScenePlyBinary,
-        aiProcess_PreTransformVertices
-    ),
-#endif
-
-#ifndef ASSIMP_BUILD_NO_3DS_EXPORTER
-    Exporter::ExportFormatEntry( "3ds", "Autodesk 3DS (legacy)", "3ds" , &ExportScene3DS,
-        aiProcess_Triangulate | aiProcess_SortByPType | aiProcess_JoinIdenticalVertices ),
-#endif
-
-#ifndef ASSIMP_BUILD_NO_GLTF_EXPORTER
-    Exporter::ExportFormatEntry( "gltf2", "GL Transmission Format v. 2", "gltf", &ExportSceneGLTF2,
-        aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
-    Exporter::ExportFormatEntry( "glb2", "GL Transmission Format v. 2 (binary)", "glb", &ExportSceneGLB2,
-        aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
-    Exporter::ExportFormatEntry( "gltf", "GL Transmission Format", "gltf", &ExportSceneGLTF,
-        aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
-    Exporter::ExportFormatEntry( "glb", "GL Transmission Format (binary)", "glb", &ExportSceneGLB,
-        aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
-#endif
-
-#ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER
-    Exporter::ExportFormatEntry( "assbin", "Assimp Binary File", "assbin" , &ExportSceneAssbin, 0 ),
-#endif
-
-#ifndef ASSIMP_BUILD_NO_ASSXML_EXPORTER
-    Exporter::ExportFormatEntry( "assxml", "Assimp XML Document", "assxml" , &ExportSceneAssxml, 0 ),
-#endif
-
-#ifndef ASSIMP_BUILD_NO_X3D_EXPORTER
-    Exporter::ExportFormatEntry( "x3d", "Extensible 3D", "x3d" , &ExportSceneX3D, 0 ),
-#endif
-
-#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
-    Exporter::ExportFormatEntry( "fbx", "Autodesk FBX (binary)", "fbx", &ExportSceneFBX, 0 ),
-    Exporter::ExportFormatEntry( "fbxa", "Autodesk FBX (ascii)", "fbx", &ExportSceneFBXA, 0 ),
-#endif
-
-#ifndef ASSIMP_BUILD_NO_M3D_EXPORTER
-    Exporter::ExportFormatEntry( "m3d", "Model 3D (binary)", "m3d", &ExportSceneM3D, 0 ),
-    Exporter::ExportFormatEntry( "a3d", "Model 3D (ascii)",  "m3d", &ExportSceneA3D, 0 ),
-#endif
-
-#ifndef ASSIMP_BUILD_NO_3MF_EXPORTER
-    Exporter::ExportFormatEntry( "3mf", "The 3MF-File-Format", "3mf", &ExportScene3MF, 0 ),
-#endif
-
-#ifndef ASSIMP_BUILD_NO_ASSJSON_EXPORTER
-    Exporter::ExportFormatEntry( "assjson", "Assimp JSON Document", "json", &ExportAssimp2Json, 0)
-#endif
-};
-
-#define ASSIMP_NUM_EXPORTERS (sizeof(gExporters)/sizeof(gExporters[0]))
-
-
-class ExporterPimpl {
-public:
-    ExporterPimpl()
-    : blob()
-    , mIOSystem(new Assimp::DefaultIOSystem())
-    , mIsDefaultIOHandler(true)
-    , mProgressHandler( nullptr )
-    , mIsDefaultProgressHandler( true )
-    , mPostProcessingSteps()
-    , mError()
-    , mExporters() {
-        GetPostProcessingStepInstanceList(mPostProcessingSteps);
-
-        // grab all built-in exporters
-        if ( 0 != ( ASSIMP_NUM_EXPORTERS ) ) {
-            mExporters.resize( ASSIMP_NUM_EXPORTERS );
-            std::copy( gExporters, gExporters + ASSIMP_NUM_EXPORTERS, mExporters.begin() );
-        }
-    }
-
-    ~ExporterPimpl() {
-        delete blob;
-
-        // Delete all post-processing plug-ins
-        for( unsigned int a = 0; a < mPostProcessingSteps.size(); a++) {
-            delete mPostProcessingSteps[a];
-        }
-        delete mProgressHandler;
-    }
-
-public:
-    aiExportDataBlob* blob;
-    std::shared_ptr< Assimp::IOSystem > mIOSystem;
-    bool mIsDefaultIOHandler;
-
-    /** The progress handler */
-    ProgressHandler *mProgressHandler;
-    bool mIsDefaultProgressHandler;
-
-    /** Post processing steps we can apply at the imported data. */
-    std::vector< BaseProcess* > mPostProcessingSteps;
-
-    /** Last fatal export error */
-    std::string mError;
-
-    /** Exporters, this includes those registered using #Assimp::Exporter::RegisterExporter */
-    std::vector<Exporter::ExportFormatEntry> mExporters;
-};
-
-} // end of namespace Assimp
-
-using namespace Assimp;
-
-// ------------------------------------------------------------------------------------------------
-Exporter :: Exporter()
-: pimpl(new ExporterPimpl()) {
-    pimpl->mProgressHandler = new DefaultProgressHandler();
-}
-
-// ------------------------------------------------------------------------------------------------
-Exporter::~Exporter() {
-    FreeBlob();
-    delete pimpl;
-}
-
-// ------------------------------------------------------------------------------------------------
-void Exporter::SetIOHandler( IOSystem* pIOHandler) {
-    pimpl->mIsDefaultIOHandler = !pIOHandler;
-    pimpl->mIOSystem.reset(pIOHandler);
-}
-
-// ------------------------------------------------------------------------------------------------
-IOSystem* Exporter::GetIOHandler() const {
-    return pimpl->mIOSystem.get();
-}
-
-// ------------------------------------------------------------------------------------------------
-bool Exporter::IsDefaultIOHandler() const {
-    return pimpl->mIsDefaultIOHandler;
-}
-
-// ------------------------------------------------------------------------------------------------
-void Exporter::SetProgressHandler(ProgressHandler* pHandler) {
-    ai_assert(nullptr != pimpl);
-
-    if ( nullptr == pHandler) {
-        // Release pointer in the possession of the caller
-        pimpl->mProgressHandler = new DefaultProgressHandler();
-        pimpl->mIsDefaultProgressHandler = true;
-        return;
-    }
-
-    if (pimpl->mProgressHandler == pHandler) {
-        return;
-    }
-
-    delete pimpl->mProgressHandler;
-    pimpl->mProgressHandler = pHandler;
-    pimpl->mIsDefaultProgressHandler = false;
-}
-
-// ------------------------------------------------------------------------------------------------
-const aiExportDataBlob* Exporter::ExportToBlob( const aiScene* pScene, const char* pFormatId,
-                                                unsigned int pPreprocessing, const ExportProperties* pProperties) {
-    if (pimpl->blob) {
-        delete pimpl->blob;
-        pimpl->blob = nullptr;
-    }
-
-    std::shared_ptr<IOSystem> old = pimpl->mIOSystem;
-    BlobIOSystem* blobio = new BlobIOSystem();
-    pimpl->mIOSystem = std::shared_ptr<IOSystem>( blobio );
-
-    if (AI_SUCCESS != Export(pScene,pFormatId,blobio->GetMagicFileName(), pPreprocessing, pProperties)) {
-        pimpl->mIOSystem = old;
-        return nullptr;
-    }
-
-    pimpl->blob = blobio->GetBlobChain();
-    pimpl->mIOSystem = old;
-
-    return pimpl->blob;
-}
-
-// ------------------------------------------------------------------------------------------------
-aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const char* pPath,
-        unsigned int pPreprocessing, const ExportProperties* pProperties) {
-    ASSIMP_BEGIN_EXCEPTION_REGION();
-
-    // when they create scenes from scratch, users will likely create them not in verbose
-    // format. They will likely not be aware that there is a flag in the scene to indicate
-    // this, however. To avoid surprises and bug reports, we check for duplicates in
-    // meshes upfront.
-    const bool is_verbose_format = !(pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) || MakeVerboseFormatProcess::IsVerboseFormat(pScene);
-
-    pimpl->mProgressHandler->UpdateFileWrite(0, 4);
-
-    pimpl->mError = "";
-    for (size_t i = 0; i < pimpl->mExporters.size(); ++i) {
-        const Exporter::ExportFormatEntry& exp = pimpl->mExporters[i];
-        if (!strcmp(exp.mDescription.id,pFormatId)) {
-            try {
-                // Always create a full copy of the scene. We might optimize this one day,
-                // but for now it is the most pragmatic way.
-                aiScene* scenecopy_tmp = nullptr;
-                SceneCombiner::CopyScene(&scenecopy_tmp,pScene);
-
-                pimpl->mProgressHandler->UpdateFileWrite(1, 4);
-
-                std::unique_ptr<aiScene> scenecopy(scenecopy_tmp);
-                const ScenePrivateData* const priv = ScenePriv(pScene);
-
-                // steps that are not idempotent, i.e. we might need to run them again, usually to get back to the
-                // original state before the step was applied first. When checking which steps we don't need
-                // to run, those are excluded.
-                const unsigned int nonIdempotentSteps = aiProcess_FlipWindingOrder | aiProcess_FlipUVs | aiProcess_MakeLeftHanded;
-
-                // Erase all pp steps that were already applied to this scene
-                const unsigned int pp = (exp.mEnforcePP | pPreprocessing) & ~(priv && !priv->mIsCopy
-                    ? (priv->mPPStepsApplied & ~nonIdempotentSteps)
-                    : 0u);
-
-                // If no extra post-processing was specified, and we obtained this scene from an
-                // Assimp importer, apply the reverse steps automatically.
-                // TODO: either drop this, or document it. Otherwise it is just a bad surprise.
-                //if (!pPreprocessing && priv) {
-                //  pp |= (nonIdempotentSteps & priv->mPPStepsApplied);
-                //}
-
-                // If the input scene is not in verbose format, but there is at least post-processing step that relies on it,
-                // we need to run the MakeVerboseFormat step first.
-                bool must_join_again = false;
-                if (!is_verbose_format) {
-                    bool verbosify = false;
-                    for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
-                        BaseProcess* const p = pimpl->mPostProcessingSteps[a];
-
-                        if (p->IsActive(pp) && p->RequireVerboseFormat()) {
-                            verbosify = true;
-                            break;
-                        }
-                    }
-
-                    if (verbosify || (exp.mEnforcePP & aiProcess_JoinIdenticalVertices)) {
-                        ASSIMP_LOG_DEBUG("export: Scene data not in verbose format, applying MakeVerboseFormat step first");
-
-                        MakeVerboseFormatProcess proc;
-                        proc.Execute(scenecopy.get());
-
-                        if(!(exp.mEnforcePP & aiProcess_JoinIdenticalVertices)) {
-                            must_join_again = true;
-                        }
-                    }
-                }
-
-                pimpl->mProgressHandler->UpdateFileWrite(2, 4);
-
-                if (pp) {
-                    // the three 'conversion' steps need to be executed first because all other steps rely on the standard data layout
-                    {
-                        FlipWindingOrderProcess step;
-                        if (step.IsActive(pp)) {
-                            step.Execute(scenecopy.get());
-                        }
-                    }
-
-                    {
-                        FlipUVsProcess step;
-                        if (step.IsActive(pp)) {
-                            step.Execute(scenecopy.get());
-                        }
-                    }
-
-                    {
-                        MakeLeftHandedProcess step;
-                        if (step.IsActive(pp)) {
-                            step.Execute(scenecopy.get());
-                        }
-                    }
-
-                    bool exportPointCloud(false);
-                    if (nullptr != pProperties) {
-                        exportPointCloud = pProperties->GetPropertyBool(AI_CONFIG_EXPORT_POINT_CLOUDS);
-                    }
-
-                    // dispatch other processes
-                    for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
-                        BaseProcess* const p = pimpl->mPostProcessingSteps[a];
-
-                        if (p->IsActive(pp)
-                            && !dynamic_cast<FlipUVsProcess*>(p)
-                            && !dynamic_cast<FlipWindingOrderProcess*>(p)
-                            && !dynamic_cast<MakeLeftHandedProcess*>(p)) {
-                            if (dynamic_cast<PretransformVertices*>(p) && exportPointCloud) {
-                                continue;
-                            }
-                            p->Execute(scenecopy.get());
-                        }
-                    }
-                    ScenePrivateData* const privOut = ScenePriv(scenecopy.get());
-                    ai_assert(nullptr != privOut);
-
-                    privOut->mPPStepsApplied |= pp;
-                }
-
-                pimpl->mProgressHandler->UpdateFileWrite(3, 4);
-
-                if(must_join_again) {
-                    JoinVerticesProcess proc;
-                    proc.Execute(scenecopy.get());
-                }
-
-                ExportProperties emptyProperties;  // Never pass NULL ExportProperties so Exporters don't have to worry.
-                ExportProperties* pProp = pProperties ? (ExportProperties*)pProperties : &emptyProperties;
-                                pProp->SetPropertyBool("bJoinIdenticalVertices", must_join_again);
-                                exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get(), pProp);
-                exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get(), pProp);
-
-                pimpl->mProgressHandler->UpdateFileWrite(4, 4);
-            } catch (DeadlyExportError& err) {
-                pimpl->mError = err.what();
-                return AI_FAILURE;
-            }
-            return AI_SUCCESS;
-        }
-    }
-
-    pimpl->mError = std::string("Found no exporter to handle this file format: ") + pFormatId;
-    ASSIMP_END_EXCEPTION_REGION(aiReturn);
-
-    return AI_FAILURE;
-}
-
-// ------------------------------------------------------------------------------------------------
-const char* Exporter::GetErrorString() const {
-    return pimpl->mError.c_str();
-}
-
-// ------------------------------------------------------------------------------------------------
-void Exporter::FreeBlob() {
-    delete pimpl->blob;
-    pimpl->blob = nullptr;
-
-    pimpl->mError = "";
-}
-
-// ------------------------------------------------------------------------------------------------
-const aiExportDataBlob* Exporter::GetBlob() const {
-    return pimpl->blob;
-}
-
-// ------------------------------------------------------------------------------------------------
-const aiExportDataBlob* Exporter::GetOrphanedBlob() const {
-    const aiExportDataBlob* tmp = pimpl->blob;
-    pimpl->blob = nullptr;
-    return tmp;
-}
-
-// ------------------------------------------------------------------------------------------------
-size_t Exporter::GetExportFormatCount() const {
-    return pimpl->mExporters.size();
-}
-
-// ------------------------------------------------------------------------------------------------
-const aiExportFormatDesc* Exporter::GetExportFormatDescription( size_t index ) const {
-    if (index >= GetExportFormatCount()) {
-        return nullptr;
-    }
-
-    // Return from static storage if the requested index is built-in.
-    if (index < sizeof(gExporters) / sizeof(gExporters[0])) {
-        return &gExporters[index].mDescription;
-    }
-
-    return &pimpl->mExporters[index].mDescription;
-}
-
-// ------------------------------------------------------------------------------------------------
-aiReturn Exporter::RegisterExporter(const ExportFormatEntry& desc) {
-    for(const ExportFormatEntry& e : pimpl->mExporters) {
-        if (!strcmp(e.mDescription.id,desc.mDescription.id)) {
-            return aiReturn_FAILURE;
-        }
-    }
-
-    pimpl->mExporters.push_back(desc);
-    return aiReturn_SUCCESS;
-}
-
-// ------------------------------------------------------------------------------------------------
-void Exporter::UnregisterExporter(const char* id) {
-    for(std::vector<ExportFormatEntry>::iterator it = pimpl->mExporters.begin();
-            it != pimpl->mExporters.end(); ++it) {
-        if (!strcmp((*it).mDescription.id,id)) {
-            pimpl->mExporters.erase(it);
-            break;
-        }
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-ExportProperties::ExportProperties() {
-    // empty
-}
-
-// ------------------------------------------------------------------------------------------------
-ExportProperties::ExportProperties(const ExportProperties &other)
-: mIntProperties(other.mIntProperties)
-, mFloatProperties(other.mFloatProperties)
-, mStringProperties(other.mStringProperties)
-, mMatrixProperties(other.mMatrixProperties) {
-    // empty
-}
-
-// ------------------------------------------------------------------------------------------------
-// Set a configuration property
-bool ExportProperties::SetPropertyInteger(const char* szName, int iValue) {
-    return SetGenericProperty<int>(mIntProperties, szName,iValue);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Set a configuration property
-bool ExportProperties::SetPropertyFloat(const char* szName, ai_real iValue) {
-    return SetGenericProperty<ai_real>(mFloatProperties, szName,iValue);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Set a configuration property
-bool ExportProperties::SetPropertyString(const char* szName, const std::string& value) {
-    return SetGenericProperty<std::string>(mStringProperties, szName,value);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Set a configuration property
-bool ExportProperties::SetPropertyMatrix(const char* szName, const aiMatrix4x4& value) {
-    return SetGenericProperty<aiMatrix4x4>(mMatrixProperties, szName,value);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Get a configuration property
-int ExportProperties::GetPropertyInteger(const char* szName, int iErrorReturn /*= 0xffffffff*/) const {
-    return GetGenericProperty<int>(mIntProperties,szName,iErrorReturn);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Get a configuration property
-ai_real ExportProperties::GetPropertyFloat(const char* szName, ai_real iErrorReturn /*= 10e10*/) const {
-    return GetGenericProperty<ai_real>(mFloatProperties,szName,iErrorReturn);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Get a configuration property
-const std::string ExportProperties::GetPropertyString(const char* szName,
-        const std::string& iErrorReturn /*= ""*/) const {
-    return GetGenericProperty<std::string>(mStringProperties,szName,iErrorReturn);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Has a configuration property
-const aiMatrix4x4 ExportProperties::GetPropertyMatrix(const char* szName,
-        const aiMatrix4x4& iErrorReturn /*= aiMatrix4x4()*/) const {
-    return GetGenericProperty<aiMatrix4x4>(mMatrixProperties,szName,iErrorReturn);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Has a configuration property
-bool ExportProperties::HasPropertyInteger(const char* szName) const {
-    return HasGenericProperty<int>(mIntProperties, szName);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Has a configuration property
-bool ExportProperties::HasPropertyBool(const char* szName) const {
-    return HasGenericProperty<int>(mIntProperties, szName);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Has a configuration property
-bool ExportProperties::HasPropertyFloat(const char* szName) const {
-    return HasGenericProperty<ai_real>(mFloatProperties, szName);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Has a configuration property
-bool ExportProperties::HasPropertyString(const char* szName) const {
-    return HasGenericProperty<std::string>(mStringProperties, szName);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Has a configuration property
-bool ExportProperties::HasPropertyMatrix(const char* szName) const {
-    return HasGenericProperty<aiMatrix4x4>(mMatrixProperties, szName);
-}
-
-
-#endif // !ASSIMP_BUILD_NO_EXPORT

+ 0 - 107
thirdparty/assimp/code/Common/FileLogStream.h

@@ -1,107 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-copyright notice, this list of conditions and the
-following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the
-following disclaimer in the documentation and/or other
-materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-contributors may be used to endorse or promote products
-derived from this software without specific prior
-written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-/** @file FileLofStream.h
-*/
-#ifndef ASSIMP_FILELOGSTREAM_H_INC
-#define ASSIMP_FILELOGSTREAM_H_INC
-
-#include <assimp/LogStream.hpp>
-#include <assimp/IOStream.hpp>
-#include <assimp/DefaultIOSystem.h>
-
-namespace Assimp    {
-
-// ----------------------------------------------------------------------------------
-/** @class  FileLogStream
- *  @brief  Logstream to write into a file.
- */
-class FileLogStream :
-    public LogStream
-{
-public:
-    FileLogStream( const char* file, IOSystem* io = NULL );
-    ~FileLogStream();
-    void write( const char* message );
-
-private:
-    IOStream *m_pStream;
-};
-
-// ----------------------------------------------------------------------------------
-//  Constructor
-inline FileLogStream::FileLogStream( const char* file, IOSystem* io ) :
-    m_pStream(NULL)
-{
-    if ( !file || 0 == *file )
-        return;
-
-    // If no IOSystem is specified: take a default one
-    if (!io)
-    {
-        DefaultIOSystem FileSystem;
-        m_pStream = FileSystem.Open( file, "wt");
-    }
-    else m_pStream = io->Open( file, "wt" );
-}
-
-// ----------------------------------------------------------------------------------
-//  Destructor
-inline FileLogStream::~FileLogStream()
-{
-    // The virtual d'tor should destroy the underlying file
-    delete m_pStream;
-}
-
-// ----------------------------------------------------------------------------------
-//  Write method
-inline void FileLogStream::write( const char* message )
-{
-    if (m_pStream != NULL)
-    {
-        m_pStream->Write(message, sizeof(char), ::strlen(message));
-        m_pStream->Flush();
-    }
-}
-
-// ----------------------------------------------------------------------------------
-} // !Namespace Assimp
-
-#endif // !! ASSIMP_FILELOGSTREAM_H_INC

+ 0 - 345
thirdparty/assimp/code/Common/FileSystemFilter.h

@@ -1,345 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2008, assimp team
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file FileSystemFilter.h
- *  Implements a filter system to filter calls to Exists() and Open()
- *  in order to improve the success rate of file opening ...
- */
-#pragma once
-#ifndef AI_FILESYSTEMFILTER_H_INC
-#define AI_FILESYSTEMFILTER_H_INC
-
-#include <assimp/IOSystem.hpp>
-#include <assimp/DefaultLogger.hpp>
-#include <assimp/fast_atof.h>
-#include <assimp/ParsingUtils.h>
-
-namespace Assimp    {
-
-inline bool IsHex(char s) {
-    return (s>='0' && s<='9') || (s>='a' && s<='f') || (s>='A' && s<='F');
-}
-
-// ---------------------------------------------------------------------------
-/** File system filter
- */
-class FileSystemFilter : public IOSystem
-{
-public:
-    /** Constructor. */
-    FileSystemFilter(const std::string& file, IOSystem* old)
-    : mWrapped  (old)
-    , mSrc_file(file)
-    , mSep(mWrapped->getOsSeparator()) {
-        ai_assert(nullptr != mWrapped);
-
-        // Determine base directory
-        mBase = mSrc_file;
-        std::string::size_type ss2;
-        if (std::string::npos != (ss2 = mBase.find_last_of("\\/")))  {
-            mBase.erase(ss2,mBase.length()-ss2);
-        } else {
-            mBase = "";
-        }
-
-        // make sure the directory is terminated properly
-        char s;
-
-        if ( mBase.empty() ) {
-            mBase = ".";
-            mBase += getOsSeparator();
-        } else if ((s = *(mBase.end()-1)) != '\\' && s != '/') {
-            mBase += getOsSeparator();
-        }
-
-        DefaultLogger::get()->info("Import root directory is \'" + mBase + "\'");
-    }
-
-    /** Destructor. */
-    ~FileSystemFilter() {
-        // empty
-    }
-
-    // -------------------------------------------------------------------
-    /** Tests for the existence of a file at the given path. */
-    bool Exists( const char* pFile) const {
-        ai_assert( nullptr != mWrapped );
-        
-        std::string tmp = pFile;
-
-        // Currently this IOSystem is also used to open THE ONE FILE.
-        if (tmp != mSrc_file)    {
-            BuildPath(tmp);
-            Cleanup(tmp);
-        }
-
-        return mWrapped->Exists(tmp);
-    }
-
-    // -------------------------------------------------------------------
-    /** Returns the directory separator. */
-    char getOsSeparator() const {
-        return mSep;
-    }
-
-    // -------------------------------------------------------------------
-    /** Open a new file with a given path. */
-    IOStream* Open( const char* pFile, const char* pMode = "rb") {
-        ai_assert( nullptr != mWrapped );
-        if ( nullptr == pFile || nullptr == pMode ) {
-            return nullptr;
-        }
-        
-        ai_assert( nullptr != pFile );
-        ai_assert( nullptr != pMode );
-
-        // First try the unchanged path
-        IOStream* s = mWrapped->Open(pFile,pMode);
-
-        if (nullptr == s) {
-            std::string tmp = pFile;
-
-            // Try to convert between absolute and relative paths
-            BuildPath(tmp);
-            s = mWrapped->Open(tmp,pMode);
-
-            if (nullptr == s) {
-                // Finally, look for typical issues with paths
-                // and try to correct them. This is our last
-                // resort.
-                tmp = pFile;
-                Cleanup(tmp);
-                BuildPath(tmp);
-                s = mWrapped->Open(tmp,pMode);
-            }
-        }
-
-        return s;
-    }
-
-    // -------------------------------------------------------------------
-    /** Closes the given file and releases all resources associated with it. */
-    void Close( IOStream* pFile) {
-        ai_assert( nullptr != mWrapped );
-        return mWrapped->Close(pFile);
-    }
-
-    // -------------------------------------------------------------------
-    /** Compare two paths */
-    bool ComparePaths (const char* one, const char* second) const {
-        ai_assert( nullptr != mWrapped );
-        return mWrapped->ComparePaths (one,second);
-    }
-
-    // -------------------------------------------------------------------
-    /** Pushes a new directory onto the directory stack. */
-    bool PushDirectory(const std::string &path ) {
-        ai_assert( nullptr != mWrapped );
-        return mWrapped->PushDirectory(path);
-    }
-
-    // -------------------------------------------------------------------
-    /** Returns the top directory from the stack. */
-    const std::string &CurrentDirectory() const {
-        ai_assert( nullptr != mWrapped );
-        return mWrapped->CurrentDirectory();
-    }
-
-    // -------------------------------------------------------------------
-    /** Returns the number of directories stored on the stack. */
-    size_t StackSize() const {
-        ai_assert( nullptr != mWrapped );
-        return mWrapped->StackSize();
-    }
-
-    // -------------------------------------------------------------------
-    /** Pops the top directory from the stack. */
-    bool PopDirectory() {
-        ai_assert( nullptr != mWrapped );
-        return mWrapped->PopDirectory();
-    }
-
-    // -------------------------------------------------------------------
-    /** Creates an new directory at the given path. */
-    bool CreateDirectory(const std::string &path) {
-        ai_assert( nullptr != mWrapped );
-        return mWrapped->CreateDirectory(path);
-    }
-
-    // -------------------------------------------------------------------
-    /** Will change the current directory to the given path. */
-    bool ChangeDirectory(const std::string &path) {
-        ai_assert( nullptr != mWrapped );
-        return mWrapped->ChangeDirectory(path);
-    }
-
-    // -------------------------------------------------------------------
-    /** Delete file. */
-    bool DeleteFile(const std::string &file) {
-        ai_assert( nullptr != mWrapped );
-        return mWrapped->DeleteFile(file);
-    }
-
-private:
-    // -------------------------------------------------------------------
-    /** Build a valid path from a given relative or absolute path.
-     */
-    void BuildPath (std::string& in) const {
-        ai_assert( nullptr != mWrapped );
-        // if we can already access the file, great.
-        if (in.length() < 3 || mWrapped->Exists(in)) {
-            return;
-        }
-
-        // Determine whether this is a relative path (Windows-specific - most assets are packaged on Windows).
-        if (in[1] != ':') {
-
-            // append base path and try
-            const std::string tmp = mBase + in;
-            if (mWrapped->Exists(tmp)) {
-                in = tmp;
-                return;
-            }
-        }
-
-        // Chop of the file name and look in the model directory, if
-        // this fails try all sub paths of the given path, i.e.
-        // if the given path is foo/bar/something.lwo, try
-        // <base>/something.lwo
-        // <base>/bar/something.lwo
-        // <base>/foo/bar/something.lwo
-        std::string::size_type pos = in.rfind('/');
-        if (std::string::npos == pos) {
-            pos = in.rfind('\\');
-        }
-
-        if (std::string::npos != pos)   {
-            std::string tmp;
-            std::string::size_type last_dirsep = std::string::npos;
-
-            while(true) {
-                tmp = mBase;
-                tmp += mSep;
-
-                std::string::size_type dirsep = in.rfind('/', last_dirsep);
-                if (std::string::npos == dirsep) {
-                    dirsep = in.rfind('\\', last_dirsep);
-                }
-
-                if (std::string::npos == dirsep || dirsep == 0) {
-                    // we did try this already.
-                    break;
-                }
-
-                last_dirsep = dirsep-1;
-
-                tmp += in.substr(dirsep+1, in.length()-pos);
-                if (mWrapped->Exists(tmp)) {
-                    in = tmp;
-                    return;
-                }
-            }
-        }
-
-        // hopefully the underlying file system has another few tricks to access this file ...
-    }
-
-    // -------------------------------------------------------------------
-    /** Cleanup the given path
-     */
-    void Cleanup (std::string& in) const {
-        if(in.empty()) {
-            return;
-        }
-
-        // Remove a very common issue when we're parsing file names: spaces at the
-        // beginning of the path.
-        char last = 0;
-        std::string::iterator it = in.begin();
-        while (IsSpaceOrNewLine( *it ))++it;
-        if (it != in.begin()) {
-            in.erase(in.begin(),it+1);
-        }
-
-        const char separator = getOsSeparator();
-        for (it = in.begin(); it != in.end(); ++it) {
-            // Exclude :// and \\, which remain untouched.
-            // https://sourceforge.net/tracker/?func=detail&aid=3031725&group_id=226462&atid=1067632
-            if ( !strncmp(&*it, "://", 3 )) {
-                it += 3;
-                continue;
-            }
-            if (it == in.begin() && !strncmp(&*it, "\\\\", 2)) {
-                it += 2;
-                continue;
-            }
-
-            // Cleanup path delimiters
-            if (*it == '/' || (*it) == '\\') {
-                *it = separator;
-
-                // And we're removing double delimiters, frequent issue with
-                // incorrectly composited paths ...
-                if (last == *it) {
-                    it = in.erase(it);
-                    --it;
-                }
-            } else if (*it == '%' && in.end() - it > 2) {
-                // Hex sequence in URIs
-                if( IsHex((&*it)[0]) && IsHex((&*it)[1]) ) {
-                    *it = HexOctetToDecimal(&*it);
-                    it = in.erase(it+1,it+2);
-                    --it;
-                }
-            }
-
-            last = *it;
-        }
-    }
-
-private:
-    IOSystem *mWrapped;
-    std::string mSrc_file, mBase;
-    char mSep;
-};
-
-} //!ns Assimp
-
-#endif //AI_DEFAULTIOSYSTEM_H_INC

+ 0 - 102
thirdparty/assimp/code/Common/IFF.h

@@ -1,102 +0,0 @@
-// Definitions for the Interchange File Format (IFF)
-// Alexander Gessler, 2006
-// Adapted to Assimp August 2008
-
-#ifndef AI_IFF_H_INCLUDED
-#define AI_IFF_H_INCLUDED
-
-#include <assimp/ByteSwapper.h>
-
-namespace Assimp    {
-namespace IFF       {
-
-/////////////////////////////////////////////////////////////////////////////////
-//! Describes an IFF chunk header
-/////////////////////////////////////////////////////////////////////////////////
-struct ChunkHeader
-{
-    //! Type of the chunk header - FourCC
-    uint32_t type;
-
-    //! Length of the chunk data, in bytes
-    uint32_t length;
-};
-
-
-/////////////////////////////////////////////////////////////////////////////////
-//! Describes an IFF sub chunk header
-/////////////////////////////////////////////////////////////////////////////////
-struct SubChunkHeader
-{
-    //! Type of the chunk header - FourCC
-    uint32_t type;
-
-    //! Length of the chunk data, in bytes
-    uint16_t length;
-};
-
-
-#define AI_IFF_FOURCC(a,b,c,d) ((uint32_t) (((uint8_t)a << 24u) | \
-    ((uint8_t)b << 16u) | ((uint8_t)c << 8u) | ((uint8_t)d)))
-
-
-#define AI_IFF_FOURCC_FORM AI_IFF_FOURCC('F','O','R','M')
-
-
-/////////////////////////////////////////////////////////////////////////////////
-//! Load a chunk header
-//! @param outFile Pointer to the file data - points to the chunk data afterwards
-//! @return Copy of the chunk header
-/////////////////////////////////////////////////////////////////////////////////
-inline ChunkHeader LoadChunk(uint8_t*& outFile)
-{
-    ChunkHeader head;
-    ::memcpy(&head.type, outFile, 4);
-    outFile += 4;
-    ::memcpy(&head.length, outFile, 4);
-    outFile += 4;
-    AI_LSWAP4(head.length);
-    AI_LSWAP4(head.type);
-    return head;
-}
-
-/////////////////////////////////////////////////////////////////////////////////
-//! Load a sub chunk header
-//! @param outFile Pointer to the file data - points to the chunk data afterwards
-//! @return Copy of the sub chunk header
-/////////////////////////////////////////////////////////////////////////////////
-inline SubChunkHeader LoadSubChunk(uint8_t*& outFile)
-{
-    SubChunkHeader head;
-    ::memcpy(&head.type, outFile, 4);
-    outFile += 4;
-    ::memcpy(&head.length, outFile, 2);
-    outFile += 2;
-    AI_LSWAP2(head.length);
-    AI_LSWAP4(head.type);
-    return head;
-}
-
-/////////////////////////////////////////////////////////////////////////////////
-//! Read the file header and return the type of the file and its size
-//! @param outFile Pointer to the file data. The buffer must at
-//!   least be 12 bytes large.
-//! @param fileType Receives the type of the file
-//! @return 0 if everything was OK, otherwise an error message
-/////////////////////////////////////////////////////////////////////////////////
-inline const char* ReadHeader(uint8_t* outFile, uint32_t& fileType)
-{
-    ChunkHeader head = LoadChunk(outFile);
-    if(AI_IFF_FOURCC_FORM != head.type)
-    {
-        return "The file is not an IFF file: FORM chunk is missing";
-    }
-    ::memcpy(&fileType, outFile, 4);
-    AI_LSWAP4(fileType);
-    return 0;
-}
-
-
-}}
-
-#endif // !! AI_IFF_H_INCLUDED

+ 0 - 1174
thirdparty/assimp/code/Common/Importer.cpp

@@ -1,1174 +0,0 @@
-/*
----------------------------------------------------------------------------
-Open Asset Import Library (assimp)
----------------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the following
-conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------------
-*/
-
-/** @file  Importer.cpp
- *  @brief Implementation of the CPP-API class #Importer
- */
-
-#include <assimp/version.h>
-#include <assimp/config.h>
-#include <assimp/importerdesc.h>
-
-// ------------------------------------------------------------------------------------------------
-/* Uncomment this line to prevent Assimp from catching unknown exceptions.
- *
- * Note that any Exception except DeadlyImportError may lead to
- * undefined behaviour -> loaders could remain in an unusable state and
- * further imports with the same Importer instance could fail/crash/burn ...
- */
-// ------------------------------------------------------------------------------------------------
-#ifndef ASSIMP_BUILD_DEBUG
-#   define ASSIMP_CATCH_GLOBAL_EXCEPTIONS
-#endif
-
-// ------------------------------------------------------------------------------------------------
-// Internal headers
-// ------------------------------------------------------------------------------------------------
-#include "Common/Importer.h"
-#include "Common/BaseProcess.h"
-#include "Common/DefaultProgressHandler.h"
-#include "PostProcessing/ProcessHelper.h"
-#include "Common/ScenePreprocessor.h"
-#include "Common/ScenePrivate.h"
-
-#include <assimp/BaseImporter.h>
-#include <assimp/GenericProperty.h>
-#include <assimp/MemoryIOWrapper.h>
-#include <assimp/Profiler.h>
-#include <assimp/TinyFormatter.h>
-#include <assimp/Exceptional.h>
-#include <assimp/Profiler.h>
-#include <set>
-#include <memory>
-#include <cctype>
-
-#include <assimp/DefaultIOStream.h>
-#include <assimp/DefaultIOSystem.h>
-
-#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
-#   include "PostProcessing/ValidateDataStructure.h"
-#endif
-
-using namespace Assimp::Profiling;
-using namespace Assimp::Formatter;
-
-namespace Assimp {
-    // ImporterRegistry.cpp
-    void GetImporterInstanceList(std::vector< BaseImporter* >& out);
-	void DeleteImporterInstanceList(std::vector< BaseImporter* >& out);
-
-    // PostStepRegistry.cpp
-    void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out);
-}
-
-using namespace Assimp;
-using namespace Assimp::Intern;
-
-// ------------------------------------------------------------------------------------------------
-// Intern::AllocateFromAssimpHeap serves as abstract base class. It overrides
-// new and delete (and their array counterparts) of public API classes (e.g. Logger) to
-// utilize our DLL heap.
-// See http://www.gotw.ca/publications/mill15.htm
-// ------------------------------------------------------------------------------------------------
-void* AllocateFromAssimpHeap::operator new ( size_t num_bytes)  {
-    return ::operator new(num_bytes);
-}
-
-void* AllocateFromAssimpHeap::operator new ( size_t num_bytes, const std::nothrow_t& ) throw()  {
-    try {
-        return AllocateFromAssimpHeap::operator new( num_bytes );
-    }
-    catch( ... )    {
-        return NULL;
-    }
-}
-
-void AllocateFromAssimpHeap::operator delete ( void* data)  {
-    return ::operator delete(data);
-}
-
-void* AllocateFromAssimpHeap::operator new[] ( size_t num_bytes)    {
-    return ::operator new[](num_bytes);
-}
-
-void* AllocateFromAssimpHeap::operator new[] ( size_t num_bytes, const std::nothrow_t& ) throw() {
-    try {
-        return AllocateFromAssimpHeap::operator new[]( num_bytes );
-    }
-    catch( ... )    {
-        return NULL;
-    }
-}
-
-void AllocateFromAssimpHeap::operator delete[] ( void* data)    {
-    return ::operator delete[](data);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Importer constructor.
-Importer::Importer()
- : pimpl( new ImporterPimpl ) {
-    pimpl->mScene = NULL;
-    pimpl->mErrorString = "";
-
-    // Allocate a default IO handler
-    pimpl->mIOHandler = new DefaultIOSystem;
-    pimpl->mIsDefaultHandler = true;
-    pimpl->bExtraVerbose     = false; // disable extra verbose mode by default
-
-    pimpl->mProgressHandler = new DefaultProgressHandler();
-    pimpl->mIsDefaultProgressHandler = true;
-
-    GetImporterInstanceList(pimpl->mImporter);
-    GetPostProcessingStepInstanceList(pimpl->mPostProcessingSteps);
-
-    // Allocate a SharedPostProcessInfo object and store pointers to it in all post-process steps in the list.
-    pimpl->mPPShared = new SharedPostProcessInfo();
-    for (std::vector<BaseProcess*>::iterator it =  pimpl->mPostProcessingSteps.begin();
-        it != pimpl->mPostProcessingSteps.end();
-        ++it)   {
-
-        (*it)->SetSharedData(pimpl->mPPShared);
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-// Destructor of Importer
-Importer::~Importer()
-{
-    // Delete all import plugins
-	DeleteImporterInstanceList(pimpl->mImporter);
-
-    // Delete all post-processing plug-ins
-    for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++)
-        delete pimpl->mPostProcessingSteps[a];
-
-    // Delete the assigned IO and progress handler
-    delete pimpl->mIOHandler;
-    delete pimpl->mProgressHandler;
-
-    // Kill imported scene. Destructor's should do that recursively
-    delete pimpl->mScene;
-
-    // Delete shared post-processing data
-    delete pimpl->mPPShared;
-
-    // and finally the pimpl itself
-    delete pimpl;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Register a custom post-processing step
-aiReturn Importer::RegisterPPStep(BaseProcess* pImp)
-{
-    ai_assert(NULL != pImp);
-    ASSIMP_BEGIN_EXCEPTION_REGION();
-
-        pimpl->mPostProcessingSteps.push_back(pImp);
-        ASSIMP_LOG_INFO("Registering custom post-processing step");
-
-    ASSIMP_END_EXCEPTION_REGION(aiReturn);
-    return AI_SUCCESS;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Register a custom loader plugin
-aiReturn Importer::RegisterLoader(BaseImporter* pImp)
-{
-    ai_assert(NULL != pImp);
-    ASSIMP_BEGIN_EXCEPTION_REGION();
-
-    // --------------------------------------------------------------------
-    // Check whether we would have two loaders for the same file extension
-    // This is absolutely OK, but we should warn the developer of the new
-    // loader that his code will probably never be called if the first
-    // loader is a bit too lazy in his file checking.
-    // --------------------------------------------------------------------
-    std::set<std::string> st;
-    std::string baked;
-    pImp->GetExtensionList(st);
-
-    for(std::set<std::string>::const_iterator it = st.begin(); it != st.end(); ++it) {
-
-#ifdef ASSIMP_BUILD_DEBUG
-        if (IsExtensionSupported(*it)) {
-            ASSIMP_LOG_WARN_F("The file extension ", *it, " is already in use");
-        }
-#endif
-        baked += *it;
-    }
-
-    // add the loader
-    pimpl->mImporter.push_back(pImp);
-    ASSIMP_LOG_INFO_F("Registering custom importer for these file extensions: ", baked);
-    ASSIMP_END_EXCEPTION_REGION(aiReturn);
-    return AI_SUCCESS;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Unregister a custom loader plugin
-aiReturn Importer::UnregisterLoader(BaseImporter* pImp)
-{
-    if(!pImp) {
-        // unregistering a NULL importer is no problem for us ... really!
-        return AI_SUCCESS;
-    }
-
-    ASSIMP_BEGIN_EXCEPTION_REGION();
-    std::vector<BaseImporter*>::iterator it = std::find(pimpl->mImporter.begin(),
-        pimpl->mImporter.end(),pImp);
-
-    if (it != pimpl->mImporter.end())   {
-        pimpl->mImporter.erase(it);
-        ASSIMP_LOG_INFO("Unregistering custom importer: ");
-        return AI_SUCCESS;
-    }
-    ASSIMP_LOG_WARN("Unable to remove custom importer: I can't find you ...");
-    ASSIMP_END_EXCEPTION_REGION(aiReturn);
-    return AI_FAILURE;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Unregister a custom loader plugin
-aiReturn Importer::UnregisterPPStep(BaseProcess* pImp)
-{
-    if(!pImp) {
-        // unregistering a NULL ppstep is no problem for us ... really!
-        return AI_SUCCESS;
-    }
-
-    ASSIMP_BEGIN_EXCEPTION_REGION();
-    std::vector<BaseProcess*>::iterator it = std::find(pimpl->mPostProcessingSteps.begin(),
-        pimpl->mPostProcessingSteps.end(),pImp);
-
-    if (it != pimpl->mPostProcessingSteps.end())    {
-        pimpl->mPostProcessingSteps.erase(it);
-        ASSIMP_LOG_INFO("Unregistering custom post-processing step");
-        return AI_SUCCESS;
-    }
-    ASSIMP_LOG_WARN("Unable to remove custom post-processing step: I can't find you ..");
-    ASSIMP_END_EXCEPTION_REGION(aiReturn);
-    return AI_FAILURE;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Supplies a custom IO handler to the importer to open and access files.
-void Importer::SetIOHandler( IOSystem* pIOHandler)
-{
-    ASSIMP_BEGIN_EXCEPTION_REGION();
-    // If the new handler is zero, allocate a default IO implementation.
-    if (!pIOHandler)
-    {
-        // Release pointer in the possession of the caller
-        pimpl->mIOHandler = new DefaultIOSystem();
-        pimpl->mIsDefaultHandler = true;
-    }
-    // Otherwise register the custom handler
-    else if (pimpl->mIOHandler != pIOHandler)
-    {
-        delete pimpl->mIOHandler;
-        pimpl->mIOHandler = pIOHandler;
-        pimpl->mIsDefaultHandler = false;
-    }
-    ASSIMP_END_EXCEPTION_REGION(void);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Get the currently set IO handler
-IOSystem* Importer::GetIOHandler() const {
-    return pimpl->mIOHandler;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Check whether a custom IO handler is currently set
-bool Importer::IsDefaultIOHandler() const {
-    return pimpl->mIsDefaultHandler;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Supplies a custom progress handler to get regular callbacks during importing
-void Importer::SetProgressHandler ( ProgressHandler* pHandler ) {
-    ASSIMP_BEGIN_EXCEPTION_REGION();
-    // If the new handler is zero, allocate a default implementation.
-    if (!pHandler)
-    {
-        // Release pointer in the possession of the caller
-        pimpl->mProgressHandler = new DefaultProgressHandler();
-        pimpl->mIsDefaultProgressHandler = true;
-    }
-    // Otherwise register the custom handler
-    else if (pimpl->mProgressHandler != pHandler)
-    {
-        delete pimpl->mProgressHandler;
-        pimpl->mProgressHandler = pHandler;
-        pimpl->mIsDefaultProgressHandler = false;
-    }
-    ASSIMP_END_EXCEPTION_REGION(void);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Get the currently set progress handler
-ProgressHandler* Importer::GetProgressHandler() const {
-    return pimpl->mProgressHandler;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Check whether a custom progress handler is currently set
-bool Importer::IsDefaultProgressHandler() const {
-    return pimpl->mIsDefaultProgressHandler;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Validate post process step flags
-bool _ValidateFlags(unsigned int pFlags)
-{
-    if (pFlags & aiProcess_GenSmoothNormals && pFlags & aiProcess_GenNormals)   {
-        ASSIMP_LOG_ERROR("#aiProcess_GenSmoothNormals and #aiProcess_GenNormals are incompatible");
-        return false;
-    }
-    if (pFlags & aiProcess_OptimizeGraph && pFlags & aiProcess_PreTransformVertices)    {
-        ASSIMP_LOG_ERROR("#aiProcess_OptimizeGraph and #aiProcess_PreTransformVertices are incompatible");
-        return false;
-    }
-    return true;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Free the current scene
-void Importer::FreeScene( )
-{
-    ASSIMP_BEGIN_EXCEPTION_REGION();
-
-    delete pimpl->mScene;
-    pimpl->mScene = NULL;
-
-    pimpl->mErrorString = "";
-    ASSIMP_END_EXCEPTION_REGION(void);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Get the current error string, if any
-const char* Importer::GetErrorString() const
-{
-     /* Must remain valid as long as ReadFile() or FreeFile() are not called */
-    return pimpl->mErrorString.c_str();
-}
-
-// ------------------------------------------------------------------------------------------------
-// Enable extra-verbose mode
-void Importer::SetExtraVerbose(bool bDo)
-{
-    pimpl->bExtraVerbose = bDo;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Get the current scene
-const aiScene* Importer::GetScene() const
-{
-    return pimpl->mScene;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Orphan the current scene and return it.
-aiScene* Importer::GetOrphanedScene()
-{
-    aiScene* s = pimpl->mScene;
-
-    ASSIMP_BEGIN_EXCEPTION_REGION();
-    pimpl->mScene = NULL;
-
-    pimpl->mErrorString = ""; /* reset error string */
-    ASSIMP_END_EXCEPTION_REGION(aiScene*);
-    return s;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Validate post-processing flags
-bool Importer::ValidateFlags(unsigned int pFlags) const
-{
-    ASSIMP_BEGIN_EXCEPTION_REGION();
-    // run basic checks for mutually exclusive flags
-    if(!_ValidateFlags(pFlags)) {
-        return false;
-    }
-
-    // ValidateDS does not anymore occur in the pp list, it plays an awesome extra role ...
-#ifdef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
-    if (pFlags & aiProcess_ValidateDataStructure) {
-        return false;
-    }
-#endif
-    pFlags &= ~aiProcess_ValidateDataStructure;
-
-    // Now iterate through all bits which are set in the flags and check whether we find at least
-    // one pp plugin which handles it.
-    for (unsigned int mask = 1; mask < (1u << (sizeof(unsigned int)*8-1));mask <<= 1) {
-
-        if (pFlags & mask) {
-
-            bool have = false;
-            for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++)   {
-                if (pimpl->mPostProcessingSteps[a]-> IsActive(mask) ) {
-
-                    have = true;
-                    break;
-                }
-            }
-            if (!have) {
-                return false;
-            }
-        }
-    }
-    ASSIMP_END_EXCEPTION_REGION(bool);
-    return true;
-}
-
-// ------------------------------------------------------------------------------------------------
-const aiScene* Importer::ReadFileFromMemory( const void* pBuffer,
-    size_t pLength,
-    unsigned int pFlags,
-    const char* pHint /*= ""*/)
-{
-    ASSIMP_BEGIN_EXCEPTION_REGION();
-    if (!pHint) {
-        pHint = "";
-    }
-
-    if (!pBuffer || !pLength || strlen(pHint) > MaxLenHint ) {
-        pimpl->mErrorString = "Invalid parameters passed to ReadFileFromMemory()";
-        return NULL;
-    }
-
-    // prevent deletion of the previous IOHandler
-    IOSystem* io = pimpl->mIOHandler;
-    pimpl->mIOHandler = NULL;
-
-    SetIOHandler(new MemoryIOSystem((const uint8_t*)pBuffer,pLength,io));
-
-    // read the file and recover the previous IOSystem
-    static const size_t BufSize(Importer::MaxLenHint + 28);
-    char fbuff[BufSize];
-    ai_snprintf(fbuff, BufSize, "%s.%s",AI_MEMORYIO_MAGIC_FILENAME,pHint);
-
-    ReadFile(fbuff,pFlags);
-    SetIOHandler(io);
-
-    ASSIMP_END_EXCEPTION_REGION(const aiScene*);
-    return pimpl->mScene;
-}
-
-// ------------------------------------------------------------------------------------------------
-void WriteLogOpening(const std::string& file)
-{
-    ASSIMP_LOG_INFO_F("Load ", file);
-
-    // print a full version dump. This is nice because we don't
-    // need to ask the authors of incoming bug reports for
-    // the library version they're using - a log dump is
-    // sufficient.
-    const unsigned int flags( aiGetCompileFlags() );
-    std::stringstream stream;
-    stream << "Assimp " << aiGetVersionMajor() << "." << aiGetVersionMinor() << "." << aiGetVersionRevision() << " "
-#if defined(ASSIMP_BUILD_ARCHITECTURE)
-        << ASSIMP_BUILD_ARCHITECTURE
-#elif defined(_M_IX86) || defined(__x86_32__) || defined(__i386__)
-        << "x86"
-#elif defined(_M_X64) || defined(__x86_64__)
-        << "amd64"
-#elif defined(_M_IA64) || defined(__ia64__)
-        << "itanium"
-#elif defined(__ppc__) || defined(__powerpc__)
-        << "ppc32"
-#elif defined(__powerpc64__)
-        << "ppc64"
-#elif defined(__arm__)
-        << "arm"
-#else
-        << "<unknown architecture>"
-#endif
-        << " "
-#if defined(ASSIMP_BUILD_COMPILER)
-        << ( ASSIMP_BUILD_COMPILER )
-#elif defined(_MSC_VER)
-        << "msvc"
-#elif defined(__GNUC__)
-        << "gcc"
-#else
-        << "<unknown compiler>"
-#endif
-
-#ifdef ASSIMP_BUILD_DEBUG
-        << " debug"
-#endif
-
-        << (flags & ASSIMP_CFLAGS_NOBOOST ? " noboost" : "")
-        << (flags & ASSIMP_CFLAGS_SHARED  ? " shared" : "")
-        << (flags & ASSIMP_CFLAGS_SINGLETHREADED  ? " singlethreaded" : "");
-
-        ASSIMP_LOG_DEBUG(stream.str());
-}
-
-// ------------------------------------------------------------------------------------------------
-// Reads the given file and returns its contents if successful.
-const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
-{
-    ASSIMP_BEGIN_EXCEPTION_REGION();
-    const std::string pFile(_pFile);
-
-    // ----------------------------------------------------------------------
-    // Put a large try block around everything to catch all std::exception's
-    // that might be thrown by STL containers or by new().
-    // ImportErrorException's are throw by ourselves and caught elsewhere.
-    //-----------------------------------------------------------------------
-
-    WriteLogOpening(pFile);
-
-#ifdef ASSIMP_CATCH_GLOBAL_EXCEPTIONS
-    try
-#endif // ! ASSIMP_CATCH_GLOBAL_EXCEPTIONS
-    {
-        // Check whether this Importer instance has already loaded
-        // a scene. In this case we need to delete the old one
-        if (pimpl->mScene)  {
-
-            ASSIMP_LOG_DEBUG("(Deleting previous scene)");
-            FreeScene();
-        }
-
-        // First check if the file is accessible at all
-        if( !pimpl->mIOHandler->Exists( pFile)) {
-
-            pimpl->mErrorString = "Unable to open file \"" + pFile + "\".";
-            ASSIMP_LOG_ERROR(pimpl->mErrorString);
-            return NULL;
-        }
-
-        std::unique_ptr<Profiler> profiler(GetPropertyInteger(AI_CONFIG_GLOB_MEASURE_TIME,0)?new Profiler():NULL);
-        if (profiler) {
-            profiler->BeginRegion("total");
-        }
-
-        // Find an worker class which can handle the file
-        BaseImporter* imp = NULL;
-        SetPropertyInteger("importerIndex", -1);
-        for( unsigned int a = 0; a < pimpl->mImporter.size(); a++)  {
-
-            if( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, false)) {
-                imp = pimpl->mImporter[a];
-                SetPropertyInteger("importerIndex", a);
-                break;
-            }
-        }
-
-        if (!imp)   {
-            // not so bad yet ... try format auto detection.
-            const std::string::size_type s = pFile.find_last_of('.');
-            if (s != std::string::npos) {
-                ASSIMP_LOG_INFO("File extension not known, trying signature-based detection");
-                for( unsigned int a = 0; a < pimpl->mImporter.size(); a++)  {
-                    if( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, true)) {
-                        imp = pimpl->mImporter[a];
-                        SetPropertyInteger("importerIndex", a);
-                        break;
-                    }
-                }
-            }
-            // Put a proper error message if no suitable importer was found
-            if( !imp)   {
-                pimpl->mErrorString = "No suitable reader found for the file format of file \"" + pFile + "\".";
-                ASSIMP_LOG_ERROR(pimpl->mErrorString);
-                return NULL;
-            }
-        }
-
-        // Get file size for progress handler
-        IOStream * fileIO = pimpl->mIOHandler->Open( pFile );
-        uint32_t fileSize = 0;
-        if (fileIO)
-        {
-            fileSize = static_cast<uint32_t>(fileIO->FileSize());
-            pimpl->mIOHandler->Close( fileIO );
-        }
-
-        // Dispatch the reading to the worker class for this format
-        const aiImporterDesc *desc( imp->GetInfo() );
-        std::string ext( "unknown" );
-        if ( NULL != desc ) {
-            ext = desc->mName;
-        }
-        ASSIMP_LOG_INFO("Found a matching importer for this file format: " + ext + "." );
-        pimpl->mProgressHandler->UpdateFileRead( 0, fileSize );
-
-        if (profiler) {
-            profiler->BeginRegion("import");
-        }
-
-        pimpl->mScene = imp->ReadFile( this, pFile, pimpl->mIOHandler);
-        pimpl->mProgressHandler->UpdateFileRead( fileSize, fileSize );
-
-        if (profiler) {
-            profiler->EndRegion("import");
-        }
-
-        SetPropertyString("sourceFilePath", pFile);
-
-        // If successful, apply all active post processing steps to the imported data
-        if( pimpl->mScene)  {
-
-#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
-            // The ValidateDS process is an exception. It is executed first, even before ScenePreprocessor is called.
-            if (pFlags & aiProcess_ValidateDataStructure)
-            {
-                ValidateDSProcess ds;
-                ds.ExecuteOnScene (this);
-                if (!pimpl->mScene) {
-                    return NULL;
-                }
-            }
-#endif // no validation
-
-            // Preprocess the scene and prepare it for post-processing
-            if (profiler) {
-                profiler->BeginRegion("preprocess");
-            }
-
-            ScenePreprocessor pre(pimpl->mScene);
-            pre.ProcessScene();
-
-            if (profiler) {
-                profiler->EndRegion("preprocess");
-            }
-
-            // Ensure that the validation process won't be called twice
-            ApplyPostProcessing(pFlags & (~aiProcess_ValidateDataStructure));
-        }
-        // if failed, extract the error string
-        else if( !pimpl->mScene) {
-            pimpl->mErrorString = imp->GetErrorText();
-        }
-
-        // clear any data allocated by post-process steps
-        pimpl->mPPShared->Clean();
-
-        if (profiler) {
-            profiler->EndRegion("total");
-        }
-    }
-#ifdef ASSIMP_CATCH_GLOBAL_EXCEPTIONS
-    catch (std::exception &e)
-    {
-#if (defined _MSC_VER) &&   (defined _CPPRTTI)
-        // if we have RTTI get the full name of the exception that occurred
-        pimpl->mErrorString = std::string(typeid( e ).name()) + ": " + e.what();
-#else
-        pimpl->mErrorString = std::string("std::exception: ") + e.what();
-#endif
-
-        ASSIMP_LOG_ERROR(pimpl->mErrorString);
-        delete pimpl->mScene; pimpl->mScene = NULL;
-    }
-#endif // ! ASSIMP_CATCH_GLOBAL_EXCEPTIONS
-
-    // either successful or failure - the pointer expresses it anyways
-    ASSIMP_END_EXCEPTION_REGION(const aiScene*);
-    return pimpl->mScene;
-}
-
-
-// ------------------------------------------------------------------------------------------------
-// Apply post-processing to the currently bound scene
-const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags)
-{
-    ASSIMP_BEGIN_EXCEPTION_REGION();
-    // Return immediately if no scene is active
-    if (!pimpl->mScene) {
-        return NULL;
-    }
-
-    // If no flags are given, return the current scene with no further action
-    if (!pFlags) {
-        return pimpl->mScene;
-    }
-
-    // In debug builds: run basic flag validation
-    ai_assert(_ValidateFlags(pFlags));
-    ASSIMP_LOG_INFO("Entering post processing pipeline");
-
-#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
-    // The ValidateDS process plays an exceptional role. It isn't contained in the global
-    // list of post-processing steps, so we need to call it manually.
-    if (pFlags & aiProcess_ValidateDataStructure)
-    {
-        ValidateDSProcess ds;
-        ds.ExecuteOnScene (this);
-        if (!pimpl->mScene) {
-            return NULL;
-        }
-    }
-#endif // no validation
-#ifdef ASSIMP_BUILD_DEBUG
-    if (pimpl->bExtraVerbose)
-    {
-#ifdef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
-        ASSIMP_LOG_ERROR("Verbose Import is not available due to build settings");
-#endif  // no validation
-        pFlags |= aiProcess_ValidateDataStructure;
-    }
-#else
-    if (pimpl->bExtraVerbose) {
-        ASSIMP_LOG_WARN("Not a debug build, ignoring extra verbose setting");
-    }
-#endif // ! DEBUG
-
-    std::unique_ptr<Profiler> profiler(GetPropertyInteger(AI_CONFIG_GLOB_MEASURE_TIME,0)?new Profiler():NULL);
-    for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++)   {
-
-        BaseProcess* process = pimpl->mPostProcessingSteps[a];
-        pimpl->mProgressHandler->UpdatePostProcess(static_cast<int>(a), static_cast<int>(pimpl->mPostProcessingSteps.size()) );
-        if( process->IsActive( pFlags)) {
-
-            if (profiler) {
-                profiler->BeginRegion("postprocess");
-            }
-
-            process->ExecuteOnScene ( this );
-
-            if (profiler) {
-                profiler->EndRegion("postprocess");
-            }
-        }
-        if( !pimpl->mScene) {
-            break;
-        }
-#ifdef ASSIMP_BUILD_DEBUG
-
-#ifdef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
-        continue;
-#endif  // no validation
-
-        // If the extra verbose mode is active, execute the ValidateDataStructureStep again - after each step
-        if (pimpl->bExtraVerbose)   {
-            ASSIMP_LOG_DEBUG("Verbose Import: re-validating data structures");
-
-            ValidateDSProcess ds;
-            ds.ExecuteOnScene (this);
-            if( !pimpl->mScene) {
-                ASSIMP_LOG_ERROR("Verbose Import: failed to re-validate data structures");
-                break;
-            }
-        }
-#endif // ! DEBUG
-    }
-    pimpl->mProgressHandler->UpdatePostProcess( static_cast<int>(pimpl->mPostProcessingSteps.size()), 
-        static_cast<int>(pimpl->mPostProcessingSteps.size()) );
-
-    // update private scene flags
-    if( pimpl->mScene )
-      ScenePriv(pimpl->mScene)->mPPStepsApplied |= pFlags;
-
-    // clear any data allocated by post-process steps
-    pimpl->mPPShared->Clean();
-    ASSIMP_LOG_INFO("Leaving post processing pipeline");
-
-    ASSIMP_END_EXCEPTION_REGION(const aiScene*);
-    return pimpl->mScene;
-}
-
-// ------------------------------------------------------------------------------------------------
-const aiScene* Importer::ApplyCustomizedPostProcessing( BaseProcess *rootProcess, bool requestValidation ) {
-    ASSIMP_BEGIN_EXCEPTION_REGION();
-
-    // Return immediately if no scene is active
-    if ( NULL == pimpl->mScene ) {
-        return NULL;
-    }
-
-    // If no flags are given, return the current scene with no further action
-    if ( NULL == rootProcess ) {
-        return pimpl->mScene;
-    }
-
-    // In debug builds: run basic flag validation
-    ASSIMP_LOG_INFO( "Entering customized post processing pipeline" );
-
-#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
-    // The ValidateDS process plays an exceptional role. It isn't contained in the global
-    // list of post-processing steps, so we need to call it manually.
-    if ( requestValidation )
-    {
-        ValidateDSProcess ds;
-        ds.ExecuteOnScene( this );
-        if ( !pimpl->mScene ) {
-            return NULL;
-        }
-    }
-#endif // no validation
-#ifdef ASSIMP_BUILD_DEBUG
-    if ( pimpl->bExtraVerbose )
-    {
-#ifdef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
-        ASSIMP_LOG_ERROR( "Verbose Import is not available due to build settings" );
-#endif  // no validation
-    }
-#else
-    if ( pimpl->bExtraVerbose ) {
-        ASSIMP_LOG_WARN( "Not a debug build, ignoring extra verbose setting" );
-    }
-#endif // ! DEBUG
-
-    std::unique_ptr<Profiler> profiler( GetPropertyInteger( AI_CONFIG_GLOB_MEASURE_TIME, 0 ) ? new Profiler() : NULL );
-
-    if ( profiler ) {
-        profiler->BeginRegion( "postprocess" );
-    }
-
-    rootProcess->ExecuteOnScene( this );
-
-    if ( profiler ) {
-        profiler->EndRegion( "postprocess" );
-    }
-
-    // If the extra verbose mode is active, execute the ValidateDataStructureStep again - after each step
-    if ( pimpl->bExtraVerbose || requestValidation  ) {
-        ASSIMP_LOG_DEBUG( "Verbose Import: revalidating data structures" );
-
-        ValidateDSProcess ds;
-        ds.ExecuteOnScene( this );
-        if ( !pimpl->mScene ) {
-            ASSIMP_LOG_ERROR( "Verbose Import: failed to revalidate data structures" );
-        }
-    }
-
-    // clear any data allocated by post-process steps
-    pimpl->mPPShared->Clean();
-    ASSIMP_LOG_INFO( "Leaving customized post processing pipeline" );
-
-    ASSIMP_END_EXCEPTION_REGION( const aiScene* );
-
-    return pimpl->mScene;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Helper function to check whether an extension is supported by ASSIMP
-bool Importer::IsExtensionSupported(const char* szExtension) const
-{
-    return nullptr != GetImporter(szExtension);
-}
-
-// ------------------------------------------------------------------------------------------------
-size_t Importer::GetImporterCount() const
-{
-    return pimpl->mImporter.size();
-}
-
-// ------------------------------------------------------------------------------------------------
-const aiImporterDesc* Importer::GetImporterInfo(size_t index) const
-{
-    if (index >= pimpl->mImporter.size()) {
-        return NULL;
-    }
-    return pimpl->mImporter[index]->GetInfo();
-}
-
-
-// ------------------------------------------------------------------------------------------------
-BaseImporter* Importer::GetImporter (size_t index) const
-{
-    if (index >= pimpl->mImporter.size()) {
-        return NULL;
-    }
-    return pimpl->mImporter[index];
-}
-
-// ------------------------------------------------------------------------------------------------
-// Find a loader plugin for a given file extension
-BaseImporter* Importer::GetImporter (const char* szExtension) const
-{
-    return GetImporter(GetImporterIndex(szExtension));
-}
-
-// ------------------------------------------------------------------------------------------------
-// Find a loader plugin for a given file extension
-size_t Importer::GetImporterIndex (const char* szExtension) const {
-    ai_assert(nullptr != szExtension);
-
-    ASSIMP_BEGIN_EXCEPTION_REGION();
-
-    // skip over wildcard and dot characters at string head --
-    for ( ; *szExtension == '*' || *szExtension == '.'; ++szExtension );
-
-    std::string ext(szExtension);
-    if (ext.empty()) {
-        return static_cast<size_t>(-1);
-    }
-    std::transform( ext.begin(), ext.end(), ext.begin(), ToLower<char> );
-
-    std::set<std::string> str;
-    for (std::vector<BaseImporter*>::const_iterator i =  pimpl->mImporter.begin();i != pimpl->mImporter.end();++i)  {
-        str.clear();
-
-        (*i)->GetExtensionList(str);
-        for (std::set<std::string>::const_iterator it = str.begin(); it != str.end(); ++it) {
-            if (ext == *it) {
-                return std::distance(static_cast< std::vector<BaseImporter*>::const_iterator >(pimpl->mImporter.begin()), i);
-            }
-        }
-    }
-    ASSIMP_END_EXCEPTION_REGION(size_t);
-    return static_cast<size_t>(-1);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Helper function to build a list of all file extensions supported by ASSIMP
-void Importer::GetExtensionList(aiString& szOut) const
-{
-    ASSIMP_BEGIN_EXCEPTION_REGION();
-    std::set<std::string> str;
-    for (std::vector<BaseImporter*>::const_iterator i =  pimpl->mImporter.begin();i != pimpl->mImporter.end();++i)  {
-        (*i)->GetExtensionList(str);
-    }
-
-	// List can be empty
-	if( !str.empty() ) {
-		for (std::set<std::string>::const_iterator it = str.begin();; ) {
-			szOut.Append("*.");
-			szOut.Append((*it).c_str());
-
-			if (++it == str.end()) {
-				break;
-			}
-			szOut.Append(";");
-		}
-	}
-    ASSIMP_END_EXCEPTION_REGION(void);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Set a configuration property
-bool Importer::SetPropertyInteger(const char* szName, int iValue)
-{
-    bool existing;
-    ASSIMP_BEGIN_EXCEPTION_REGION();
-        existing = SetGenericProperty<int>(pimpl->mIntProperties, szName,iValue);
-    ASSIMP_END_EXCEPTION_REGION(bool);
-    return existing;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Set a configuration property
-bool Importer::SetPropertyFloat(const char* szName, ai_real iValue)
-{
-    bool existing;
-    ASSIMP_BEGIN_EXCEPTION_REGION();
-        existing = SetGenericProperty<ai_real>(pimpl->mFloatProperties, szName,iValue);
-    ASSIMP_END_EXCEPTION_REGION(bool);
-    return existing;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Set a configuration property
-bool Importer::SetPropertyString(const char* szName, const std::string& value)
-{
-    bool existing;
-    ASSIMP_BEGIN_EXCEPTION_REGION();
-        existing = SetGenericProperty<std::string>(pimpl->mStringProperties, szName,value);
-    ASSIMP_END_EXCEPTION_REGION(bool);
-    return existing;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Set a configuration property
-bool Importer::SetPropertyMatrix(const char* szName, const aiMatrix4x4& value)
-{
-    bool existing;
-    ASSIMP_BEGIN_EXCEPTION_REGION();
-        existing = SetGenericProperty<aiMatrix4x4>(pimpl->mMatrixProperties, szName,value);
-    ASSIMP_END_EXCEPTION_REGION(bool);
-    return existing;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Get a configuration property
-int Importer::GetPropertyInteger(const char* szName,
-    int iErrorReturn /*= 0xffffffff*/) const
-{
-    return GetGenericProperty<int>(pimpl->mIntProperties,szName,iErrorReturn);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Get a configuration property
-ai_real Importer::GetPropertyFloat(const char* szName,
-    ai_real iErrorReturn /*= 10e10*/) const
-{
-    return GetGenericProperty<ai_real>(pimpl->mFloatProperties,szName,iErrorReturn);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Get a configuration property
-const std::string Importer::GetPropertyString(const char* szName,
-    const std::string& iErrorReturn /*= ""*/) const
-{
-    return GetGenericProperty<std::string>(pimpl->mStringProperties,szName,iErrorReturn);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Get a configuration property
-const aiMatrix4x4 Importer::GetPropertyMatrix(const char* szName,
-    const aiMatrix4x4& iErrorReturn /*= aiMatrix4x4()*/) const
-{
-    return GetGenericProperty<aiMatrix4x4>(pimpl->mMatrixProperties,szName,iErrorReturn);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Get the memory requirements of a single node
-inline void AddNodeWeight(unsigned int& iScene,const aiNode* pcNode)
-{
-    iScene += sizeof(aiNode);
-    iScene += sizeof(unsigned int) * pcNode->mNumMeshes;
-    iScene += sizeof(void*) * pcNode->mNumChildren;
-
-    for (unsigned int i = 0; i < pcNode->mNumChildren;++i) {
-        AddNodeWeight(iScene,pcNode->mChildren[i]);
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-// Get the memory requirements of the scene
-void Importer::GetMemoryRequirements(aiMemoryInfo& in) const
-{
-    in = aiMemoryInfo();
-    aiScene* mScene = pimpl->mScene;
-
-    // return if we have no scene loaded
-    if (!pimpl->mScene)
-        return;
-
-
-    in.total = sizeof(aiScene);
-
-    // add all meshes
-    for (unsigned int i = 0; i < mScene->mNumMeshes;++i)
-    {
-        in.meshes += sizeof(aiMesh);
-        if (mScene->mMeshes[i]->HasPositions()) {
-            in.meshes += sizeof(aiVector3D) * mScene->mMeshes[i]->mNumVertices;
-        }
-
-        if (mScene->mMeshes[i]->HasNormals()) {
-            in.meshes += sizeof(aiVector3D) * mScene->mMeshes[i]->mNumVertices;
-        }
-
-        if (mScene->mMeshes[i]->HasTangentsAndBitangents()) {
-            in.meshes += sizeof(aiVector3D) * mScene->mMeshes[i]->mNumVertices * 2;
-        }
-
-        for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS;++a) {
-            if (mScene->mMeshes[i]->HasVertexColors(a)) {
-                in.meshes += sizeof(aiColor4D) * mScene->mMeshes[i]->mNumVertices;
-            }
-            else break;
-        }
-        for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS;++a) {
-            if (mScene->mMeshes[i]->HasTextureCoords(a)) {
-                in.meshes += sizeof(aiVector3D) * mScene->mMeshes[i]->mNumVertices;
-            }
-            else break;
-        }
-        if (mScene->mMeshes[i]->HasBones()) {
-            in.meshes += sizeof(void*) * mScene->mMeshes[i]->mNumBones;
-            for (unsigned int p = 0; p < mScene->mMeshes[i]->mNumBones;++p) {
-                in.meshes += sizeof(aiBone);
-                in.meshes += mScene->mMeshes[i]->mBones[p]->mNumWeights * sizeof(aiVertexWeight);
-            }
-        }
-        in.meshes += (sizeof(aiFace) + 3 * sizeof(unsigned int))*mScene->mMeshes[i]->mNumFaces;
-    }
-    in.total += in.meshes;
-
-    // add all embedded textures
-    for (unsigned int i = 0; i < mScene->mNumTextures;++i) {
-        const aiTexture* pc = mScene->mTextures[i];
-        in.textures += sizeof(aiTexture);
-        if (pc->mHeight) {
-            in.textures += 4 * pc->mHeight * pc->mWidth;
-        }
-        else in.textures += pc->mWidth;
-    }
-    in.total += in.textures;
-
-    // add all animations
-    for (unsigned int i = 0; i < mScene->mNumAnimations;++i) {
-        const aiAnimation* pc = mScene->mAnimations[i];
-        in.animations += sizeof(aiAnimation);
-
-        // add all bone anims
-        for (unsigned int a = 0; a < pc->mNumChannels; ++a) {
-            const aiNodeAnim* pc2 = pc->mChannels[i];
-            in.animations += sizeof(aiNodeAnim);
-            in.animations += pc2->mNumPositionKeys * sizeof(aiVectorKey);
-            in.animations += pc2->mNumScalingKeys * sizeof(aiVectorKey);
-            in.animations += pc2->mNumRotationKeys * sizeof(aiQuatKey);
-        }
-    }
-    in.total += in.animations;
-
-    // add all cameras and all lights
-    in.total += in.cameras = sizeof(aiCamera) *  mScene->mNumCameras;
-    in.total += in.lights  = sizeof(aiLight)  *  mScene->mNumLights;
-
-    // add all nodes
-    AddNodeWeight(in.nodes,mScene->mRootNode);
-    in.total += in.nodes;
-
-    // add all materials
-    for (unsigned int i = 0; i < mScene->mNumMaterials;++i) {
-        const aiMaterial* pc = mScene->mMaterials[i];
-        in.materials += sizeof(aiMaterial);
-        in.materials += pc->mNumAllocated * sizeof(void*);
-
-        for (unsigned int a = 0; a < pc->mNumProperties;++a) {
-            in.materials += pc->mProperties[a]->mDataLength;
-        }
-    }
-    in.total += in.materials;
-}

+ 0 - 247
thirdparty/assimp/code/Common/Importer.h

@@ -1,247 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file Importer.h mostly internal stuff for use by #Assimp::Importer */
-#pragma once
-#ifndef INCLUDED_AI_IMPORTER_H
-#define INCLUDED_AI_IMPORTER_H
-
-#include <map>
-#include <vector>
-#include <string>
-#include <assimp/matrix4x4.h>
-
-struct aiScene;
-
-namespace Assimp    {
-    class ProgressHandler;
-    class IOSystem;
-    class BaseImporter;
-    class BaseProcess;
-    class SharedPostProcessInfo;
-
-
-//! @cond never
-// ---------------------------------------------------------------------------
-/** @brief Internal PIMPL implementation for Assimp::Importer
- *
- *  Using this idiom here allows us to drop the dependency from
- *  std::vector and std::map in the public headers. Furthermore we are dropping
- *  any STL interface problems caused by mismatching STL settings. All
- *  size calculation are now done by us, not the app heap. */
-class ImporterPimpl {
-public:
-    // Data type to store the key hash
-    typedef unsigned int KeyType;
-
-    // typedefs for our four configuration maps.
-    // We don't need more, so there is no need for a generic solution
-    typedef std::map<KeyType, int> IntPropertyMap;
-    typedef std::map<KeyType, ai_real> FloatPropertyMap;
-    typedef std::map<KeyType, std::string> StringPropertyMap;
-    typedef std::map<KeyType, aiMatrix4x4> MatrixPropertyMap;
-
-    /** IO handler to use for all file accesses. */
-    IOSystem* mIOHandler;
-    bool mIsDefaultHandler;
-
-    /** Progress handler for feedback. */
-    ProgressHandler* mProgressHandler;
-    bool mIsDefaultProgressHandler;
-
-    /** Format-specific importer worker objects - one for each format we can read.*/
-    std::vector< BaseImporter* > mImporter;
-
-    /** Post processing steps we can apply at the imported data. */
-    std::vector< BaseProcess* > mPostProcessingSteps;
-
-    /** The imported data, if ReadFile() was successful, NULL otherwise. */
-    aiScene* mScene;
-
-    /** The error description, if there was one. */
-    std::string mErrorString;
-
-    /** List of integer properties */
-    IntPropertyMap mIntProperties;
-
-    /** List of floating-point properties */
-    FloatPropertyMap mFloatProperties;
-
-    /** List of string properties */
-    StringPropertyMap mStringProperties;
-
-    /** List of Matrix properties */
-    MatrixPropertyMap mMatrixProperties;
-
-    /** Used for testing - extra verbose mode causes the ValidateDataStructure-Step
-     *  to be executed before and after every single post-process step */
-    bool bExtraVerbose;
-
-    /** Used by post-process steps to share data */
-    SharedPostProcessInfo* mPPShared;
-
-    /// The default class constructor.
-    ImporterPimpl() AI_NO_EXCEPT;
-};
-
-inline
-ImporterPimpl::ImporterPimpl() AI_NO_EXCEPT
-: mIOHandler( nullptr )
-, mIsDefaultHandler( false )
-, mProgressHandler( nullptr )
-, mIsDefaultProgressHandler( false )
-, mImporter()
-, mPostProcessingSteps()
-, mScene( nullptr )
-, mErrorString()
-, mIntProperties()
-, mFloatProperties()
-, mStringProperties()
-, mMatrixProperties()
-, bExtraVerbose( false )
-, mPPShared( nullptr ) {
-    // empty
-}
-//! @endcond
-
-
-struct BatchData;
-
-// ---------------------------------------------------------------------------
-/** FOR IMPORTER PLUGINS ONLY: A helper class to the pleasure of importers
- *  that need to load many external meshes recursively.
- *
- *  The class uses several threads to load these meshes (or at least it
- *  could, this has not yet been implemented at the moment).
- *
- *  @note The class may not be used by more than one thread*/
-class ASSIMP_API BatchLoader
-{
-    // friend of Importer
-
-public:
-    //! @cond never
-    // -------------------------------------------------------------------
-    /** Wraps a full list of configuration properties for an importer.
-     *  Properties can be set using SetGenericProperty */
-    struct PropertyMap
-    {
-        ImporterPimpl::IntPropertyMap     ints;
-        ImporterPimpl::FloatPropertyMap   floats;
-        ImporterPimpl::StringPropertyMap  strings;
-        ImporterPimpl::MatrixPropertyMap  matrices;
-
-        bool operator == (const PropertyMap& prop) const {
-            // fixme: really isocpp? gcc complains
-            return ints == prop.ints && floats == prop.floats && strings == prop.strings && matrices == prop.matrices;
-        }
-
-        bool empty () const {
-            return ints.empty() && floats.empty() && strings.empty() && matrices.empty();
-        }
-    };
-    //! @endcond
-
-public:
-    // -------------------------------------------------------------------
-    /** Construct a batch loader from a given IO system to be used
-     *  to access external files 
-     */
-    explicit BatchLoader(IOSystem* pIO, bool validate = false );
-
-    // -------------------------------------------------------------------
-    /** The class destructor.
-     */
-    ~BatchLoader();
-
-    // -------------------------------------------------------------------
-    /** Sets the validation step. True for enable validation during postprocess.
-     *  @param  enable  True for validation.
-     */
-    void setValidation( bool enabled );
-    
-    // -------------------------------------------------------------------
-    /** Returns the current validation step.
-     *  @return The current validation step.
-     */
-    bool getValidation() const;
-    
-    // -------------------------------------------------------------------
-    /** Add a new file to the list of files to be loaded.
-     *  @param file File to be loaded
-     *  @param steps Post-processing steps to be executed on the file
-     *  @param map Optional configuration properties
-     *  @return 'Load request channel' - an unique ID that can later
-     *    be used to access the imported file data.
-     *  @see GetImport */
-    unsigned int AddLoadRequest (
-        const std::string& file,
-        unsigned int steps = 0,
-        const PropertyMap* map = NULL
-        );
-
-    // -------------------------------------------------------------------
-    /** Get an imported scene.
-     *  This polls the import from the internal request list.
-     *  If an import is requested several times, this function
-     *  can be called several times, too.
-     *
-     *  @param which LRWC returned by AddLoadRequest().
-     *  @return NULL if there is no scene with this file name
-     *  in the queue of the scene hasn't been loaded yet. */
-    aiScene* GetImport(
-        unsigned int which
-        );
-
-    // -------------------------------------------------------------------
-    /** Waits until all scenes have been loaded. This returns
-     *  immediately if no scenes are queued.*/
-    void LoadAll();
-
-private:
-    // No need to have that in the public API ...
-    BatchData *m_data;
-};
-
-} // Namespace Assimp
-
-#endif // INCLUDED_AI_IMPORTER_H

+ 0 - 377
thirdparty/assimp/code/Common/ImporterRegistry.cpp

@@ -1,377 +0,0 @@
-/*
----------------------------------------------------------------------------
-Open Asset Import Library (assimp)
----------------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the following
-conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------------
-*/
-
-/** @file ImporterRegistry.cpp
-
-Central registry for all importers available. Do not edit this file
-directly (unless you are adding new loaders), instead use the
-corresponding preprocessor flag to selectively disable formats.
-*/
-
-#include <vector>
-#include <assimp/BaseImporter.h>
-
-// ------------------------------------------------------------------------------------------------
-// Importers
-// (include_new_importers_here)
-// ------------------------------------------------------------------------------------------------
-#ifndef ASSIMP_BUILD_NO_X_IMPORTER
-#   include "X/XFileImporter.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_AMF_IMPORTER
-#   include "AMF/AMFImporter.hpp"
-#endif
-#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
-#   include "3DS/3DSLoader.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_MD3_IMPORTER
-#   include "MD3/MD3Loader.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_MDL_IMPORTER
-#   include "MDL/MDLLoader.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_MD2_IMPORTER
-#   include "MD2/MD2Loader.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_PLY_IMPORTER
-#   include "Ply/PlyLoader.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_ASE_IMPORTER
-#   include "ASE/ASELoader.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_OBJ_IMPORTER
-#   include "Obj/ObjFileImporter.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_HMP_IMPORTER
-#   include "HMP/HMPLoader.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_SMD_IMPORTER
-#   include "SMD/SMDLoader.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_MDC_IMPORTER
-#   include "MDC/MDCLoader.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_MD5_IMPORTER
-#   include "MD5/MD5Loader.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_STL_IMPORTER
-#   include "STL/STLLoader.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_LWO_IMPORTER
-#   include "LWO/LWOLoader.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_DXF_IMPORTER
-#   include "DXF/DXFLoader.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_NFF_IMPORTER
-#   include "NFF/NFFLoader.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_RAW_IMPORTER
-#   include "Raw/RawLoader.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_SIB_IMPORTER
-#   include "SIB/SIBImporter.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_OFF_IMPORTER
-#   include "OFF/OFFLoader.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_AC_IMPORTER
-#   include "AC/ACLoader.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_BVH_IMPORTER
-#   include "BVH/BVHLoader.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_IRRMESH_IMPORTER
-#   include "Irr/IRRMeshLoader.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_IRR_IMPORTER
-#   include "Irr/IRRLoader.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_Q3D_IMPORTER
-#   include "Q3D/Q3DLoader.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_B3D_IMPORTER
-#   include "B3D/B3DImporter.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_COLLADA_IMPORTER
-#   include "Collada/ColladaLoader.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_TERRAGEN_IMPORTER
-#   include "Terragen/TerragenLoader.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_CSM_IMPORTER
-#   include "CSM/CSMLoader.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_3D_IMPORTER
-#   include "Unreal/UnrealLoader.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_LWS_IMPORTER
-#   include "LWS/LWSLoader.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
-#   include "Ogre/OgreImporter.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_OPENGEX_IMPORTER
-#   include "OpenGEX/OpenGEXImporter.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_MS3D_IMPORTER
-#   include "MS3D/MS3DLoader.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_COB_IMPORTER
-#   include "COB/COBLoader.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
-#   include "Blender/BlenderLoader.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER
-#   include "Q3BSP/Q3BSPFileImporter.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_NDO_IMPORTER
-#   include "NDO/NDOLoader.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
-#   include "Importer/IFC/IFCLoader.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_XGL_IMPORTER
-#   include "XGL/XGLLoader.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
-#   include "FBX/FBXImporter.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER
-#   include "Assbin/AssbinLoader.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER
-#   include "glTF/glTFImporter.h"
-#   include "glTF2/glTF2Importer.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_C4D_IMPORTER
-#   include "C4D/C4DImporter.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_3MF_IMPORTER
-#   include "3MF/D3MFImporter.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
-#   include "X3D/X3DImporter.hpp"
-#endif
-#ifndef ASSIMP_BUILD_NO_MMD_IMPORTER
-#   include "MMD/MMDImporter.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_M3D_IMPORTER
-#   include "M3D/M3DImporter.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_STEP_IMPORTER
-#   include "Importer/StepFile/StepFileImporter.h"
-#endif
-
-namespace Assimp {
-
-// ------------------------------------------------------------------------------------------------
-void GetImporterInstanceList(std::vector< BaseImporter* >& out)
-{
-    // ----------------------------------------------------------------------------
-    // Add an instance of each worker class here
-    // (register_new_importers_here)
-    // ----------------------------------------------------------------------------
-    out.reserve(64);
-#if (!defined ASSIMP_BUILD_NO_X_IMPORTER)
-    out.push_back( new XFileImporter());
-#endif
-#if (!defined ASSIMP_BUILD_NO_OBJ_IMPORTER)
-    out.push_back( new ObjFileImporter());
-#endif
-#ifndef ASSIMP_BUILD_NO_AMF_IMPORTER
-	out.push_back( new AMFImporter() );
-#endif
-#if (!defined ASSIMP_BUILD_NO_3DS_IMPORTER)
-    out.push_back( new Discreet3DSImporter());
-#endif
-#if (!defined ASSIMP_BUILD_NO_M3D_IMPORTER)
-    out.push_back( new M3DImporter());
-#endif
-#if (!defined ASSIMP_BUILD_NO_MD3_IMPORTER)
-    out.push_back( new MD3Importer());
-#endif
-#if (!defined ASSIMP_BUILD_NO_MD2_IMPORTER)
-    out.push_back( new MD2Importer());
-#endif
-#if (!defined ASSIMP_BUILD_NO_PLY_IMPORTER)
-    out.push_back( new PLYImporter());
-#endif
-#if (!defined ASSIMP_BUILD_NO_MDL_IMPORTER)
-    out.push_back( new MDLImporter());
-#endif
-#if (!defined ASSIMP_BUILD_NO_ASE_IMPORTER)
-  #if (!defined ASSIMP_BUILD_NO_3DS_IMPORTER)
-    out.push_back( new ASEImporter());
-#  endif
-#endif
-#if (!defined ASSIMP_BUILD_NO_HMP_IMPORTER)
-    out.push_back( new HMPImporter());
-#endif
-#if (!defined ASSIMP_BUILD_NO_SMD_IMPORTER)
-    out.push_back( new SMDImporter());
-#endif
-#if (!defined ASSIMP_BUILD_NO_MDC_IMPORTER)
-    out.push_back( new MDCImporter());
-#endif
-#if (!defined ASSIMP_BUILD_NO_MD5_IMPORTER)
-    out.push_back( new MD5Importer());
-#endif
-#if (!defined ASSIMP_BUILD_NO_STL_IMPORTER)
-    out.push_back( new STLImporter());
-#endif
-#if (!defined ASSIMP_BUILD_NO_LWO_IMPORTER)
-    out.push_back( new LWOImporter());
-#endif
-#if (!defined ASSIMP_BUILD_NO_DXF_IMPORTER)
-    out.push_back( new DXFImporter());
-#endif
-#if (!defined ASSIMP_BUILD_NO_NFF_IMPORTER)
-    out.push_back( new NFFImporter());
-#endif
-#if (!defined ASSIMP_BUILD_NO_RAW_IMPORTER)
-    out.push_back( new RAWImporter());
-#endif
-#if (!defined ASSIMP_BUILD_NO_SIB_IMPORTER)
-    out.push_back( new SIBImporter());
-#endif
-#if (!defined ASSIMP_BUILD_NO_OFF_IMPORTER)
-    out.push_back( new OFFImporter());
-#endif
-#if (!defined ASSIMP_BUILD_NO_AC_IMPORTER)
-    out.push_back( new AC3DImporter());
-#endif
-#if (!defined ASSIMP_BUILD_NO_BVH_IMPORTER)
-    out.push_back( new BVHLoader());
-#endif
-#if (!defined ASSIMP_BUILD_NO_IRRMESH_IMPORTER)
-    out.push_back( new IRRMeshImporter());
-#endif
-#if (!defined ASSIMP_BUILD_NO_IRR_IMPORTER)
-    out.push_back( new IRRImporter());
-#endif
-#if (!defined ASSIMP_BUILD_NO_Q3D_IMPORTER)
-    out.push_back( new Q3DImporter());
-#endif
-#if (!defined ASSIMP_BUILD_NO_B3D_IMPORTER)
-    out.push_back( new B3DImporter());
-#endif
-#if (!defined ASSIMP_BUILD_NO_COLLADA_IMPORTER)
-    out.push_back( new ColladaLoader());
-#endif
-#if (!defined ASSIMP_BUILD_NO_TERRAGEN_IMPORTER)
-    out.push_back( new TerragenImporter());
-#endif
-#if (!defined ASSIMP_BUILD_NO_CSM_IMPORTER)
-    out.push_back( new CSMImporter());
-#endif
-#if (!defined ASSIMP_BUILD_NO_3D_IMPORTER)
-    out.push_back( new UnrealImporter());
-#endif
-#if (!defined ASSIMP_BUILD_NO_LWS_IMPORTER)
-    out.push_back( new LWSImporter());
-#endif
-#if (!defined ASSIMP_BUILD_NO_OGRE_IMPORTER)
-    out.push_back( new Ogre::OgreImporter());
-#endif
-#if (!defined ASSIMP_BUILD_NO_OPENGEX_IMPORTER )
-    out.push_back( new OpenGEX::OpenGEXImporter() );
-#endif
-#if (!defined ASSIMP_BUILD_NO_MS3D_IMPORTER)
-    out.push_back( new MS3DImporter());
-#endif
-#if (!defined ASSIMP_BUILD_NO_COB_IMPORTER)
-    out.push_back( new COBImporter());
-#endif
-#if (!defined ASSIMP_BUILD_NO_BLEND_IMPORTER)
-    out.push_back( new BlenderImporter());
-#endif
-#if (!defined ASSIMP_BUILD_NO_Q3BSP_IMPORTER)
-    out.push_back( new Q3BSPFileImporter() );
-#endif
-#if (!defined ASSIMP_BUILD_NO_NDO_IMPORTER)
-    out.push_back( new NDOImporter() );
-#endif
-#if (!defined ASSIMP_BUILD_NO_IFC_IMPORTER)
-    out.push_back( new IFCImporter() );
-#endif
-#if ( !defined ASSIMP_BUILD_NO_XGL_IMPORTER )
-    out.push_back( new XGLImporter() );
-#endif
-#if ( !defined ASSIMP_BUILD_NO_FBX_IMPORTER )
-    out.push_back( new FBXImporter() );
-#endif
-#if ( !defined ASSIMP_BUILD_NO_ASSBIN_IMPORTER )
-    out.push_back( new AssbinImporter() );
-#endif
-#if ( !defined ASSIMP_BUILD_NO_GLTF_IMPORTER )
-    out.push_back( new glTFImporter() );
-    out.push_back( new glTF2Importer() );
-#endif
-#if ( !defined ASSIMP_BUILD_NO_C4D_IMPORTER )
-    out.push_back( new C4DImporter() );
-#endif
-#if ( !defined ASSIMP_BUILD_NO_3MF_IMPORTER )
-    out.push_back( new D3MFImporter() );
-#endif
-#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
-    out.push_back( new X3DImporter() );
-#endif
-#ifndef ASSIMP_BUILD_NO_MMD_IMPORTER
-    out.push_back( new MMDImporter() );
-#endif
-#ifndef ASSIMP_BUILD_NO_STEP_IMPORTER
-    out.push_back(new StepFile::StepFileImporter());
-#endif
-}
-
-/** will delete all registered importers. */
-void DeleteImporterInstanceList(std::vector< BaseImporter* >& deleteList){
-	for(size_t i= 0; i<deleteList.size();++i){
-		delete deleteList[i];
-		deleteList[i]=nullptr;
-	}//for
-}
-
-} // namespace Assimp

+ 0 - 229
thirdparty/assimp/code/Common/PolyTools.h

@@ -1,229 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file PolyTools.h, various utilities for our dealings with arbitrary polygons */
-
-#ifndef AI_POLYTOOLS_H_INCLUDED
-#define AI_POLYTOOLS_H_INCLUDED
-
-#include <assimp/material.h>
-#include <assimp/ai_assert.h>
-
-namespace Assimp {
-
-// -------------------------------------------------------------------------------
-/** Compute the signed area of a triangle.
- *  The function accepts an unconstrained template parameter for use with
- *  both aiVector3D and aiVector2D, but generally ignores the third coordinate.*/
-template <typename T>
-inline double GetArea2D(const T& v1, const T& v2, const T& v3)
-{
-    return 0.5 * (v1.x * ((double)v3.y - v2.y) + v2.x * ((double)v1.y - v3.y) + v3.x * ((double)v2.y - v1.y));
-}
-
-// -------------------------------------------------------------------------------
-/** Test if a given point p2 is on the left side of the line formed by p0-p1.
- *  The function accepts an unconstrained template parameter for use with
- *  both aiVector3D and aiVector2D, but generally ignores the third coordinate.*/
-template <typename T>
-inline bool OnLeftSideOfLine2D(const T& p0, const T& p1,const T& p2)
-{
-    return GetArea2D(p0,p2,p1) > 0;
-}
-
-// -------------------------------------------------------------------------------
-/** Test if a given point is inside a given triangle in R2.
- * The function accepts an unconstrained template parameter for use with
- *  both aiVector3D and aiVector2D, but generally ignores the third coordinate.*/
-template <typename T>
-inline bool PointInTriangle2D(const T& p0, const T& p1,const T& p2, const T& pp)
-{
-    // Point in triangle test using baryzentric coordinates
-    const aiVector2D v0 = p1 - p0;
-    const aiVector2D v1 = p2 - p0;
-    const aiVector2D v2 = pp - p0;
-
-    double dot00 = v0 * v0;
-    double dot01 = v0 * v1;
-    double dot02 = v0 * v2;
-    double dot11 = v1 * v1;
-    double dot12 = v1 * v2;
-
-    const double invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
-    dot11 = (dot11 * dot02 - dot01 * dot12) * invDenom;
-    dot00 = (dot00 * dot12 - dot01 * dot02) * invDenom;
-
-    return (dot11 > 0) && (dot00 > 0) && (dot11 + dot00 < 1);
-}
-
-
-// -------------------------------------------------------------------------------
-/** Check whether the winding order of a given polygon is counter-clockwise.
- *  The function accepts an unconstrained template parameter, but is intended
- *  to be used only with aiVector2D and aiVector3D (z axis is ignored, only
- *  x and y are taken into account).
- * @note Code taken from http://cgm.cs.mcgill.ca/~godfried/teaching/cg-projects/97/Ian/applet1.html and translated to C++
- */
-template <typename T>
-inline bool IsCCW(T* in, size_t npoints) {
-    double aa, bb, cc, b, c, theta;
-    double convex_turn;
-    double convex_sum = 0;
-
-    ai_assert(npoints >= 3);
-
-    for (size_t i = 0; i < npoints - 2; i++) {
-        aa = ((in[i+2].x - in[i].x) * (in[i+2].x - in[i].x)) +
-            ((-in[i+2].y + in[i].y) * (-in[i+2].y + in[i].y));
-
-        bb = ((in[i+1].x - in[i].x) * (in[i+1].x - in[i].x)) +
-            ((-in[i+1].y + in[i].y) * (-in[i+1].y + in[i].y));
-
-        cc = ((in[i+2].x - in[i+1].x) *
-            (in[i+2].x - in[i+1].x)) +
-            ((-in[i+2].y + in[i+1].y) *
-            (-in[i+2].y + in[i+1].y));
-
-        b = std::sqrt(bb);
-        c = std::sqrt(cc);
-        theta = std::acos((bb + cc - aa) / (2 * b * c));
-
-        if (OnLeftSideOfLine2D(in[i],in[i+2],in[i+1])) {
-            //  if (convex(in[i].x, in[i].y,
-            //      in[i+1].x, in[i+1].y,
-            //      in[i+2].x, in[i+2].y)) {
-            convex_turn = AI_MATH_PI_F - theta;
-            convex_sum += convex_turn;
-        }
-        else {
-            convex_sum -= AI_MATH_PI_F - theta;
-        }
-    }
-    aa = ((in[1].x - in[npoints-2].x) *
-        (in[1].x - in[npoints-2].x)) +
-        ((-in[1].y + in[npoints-2].y) *
-        (-in[1].y + in[npoints-2].y));
-
-    bb = ((in[0].x - in[npoints-2].x) *
-        (in[0].x - in[npoints-2].x)) +
-        ((-in[0].y + in[npoints-2].y) *
-        (-in[0].y + in[npoints-2].y));
-
-    cc = ((in[1].x - in[0].x) * (in[1].x - in[0].x)) +
-        ((-in[1].y + in[0].y) * (-in[1].y + in[0].y));
-
-    b = std::sqrt(bb);
-    c = std::sqrt(cc);
-    theta = std::acos((bb + cc - aa) / (2 * b * c));
-
-    //if (convex(in[npoints-2].x, in[npoints-2].y,
-    //  in[0].x, in[0].y,
-    //  in[1].x, in[1].y)) {
-    if (OnLeftSideOfLine2D(in[npoints-2],in[1],in[0])) {
-        convex_turn = AI_MATH_PI_F - theta;
-        convex_sum += convex_turn;
-    }
-    else {
-        convex_sum -= AI_MATH_PI_F - theta;
-    }
-
-    return convex_sum >= (2 * AI_MATH_PI_F);
-}
-
-
-// -------------------------------------------------------------------------------
-/** Compute the normal of an arbitrary polygon in R3.
- *
- *  The code is based on Newell's formula, that is a polygons normal is the ratio
- *  of its area when projected onto the three coordinate axes.
- *
- *  @param out Receives the output normal
- *  @param num Number of input vertices
- *  @param x X data source. x[ofs_x*n] is the n'th element.
- *  @param y Y data source. y[ofs_y*n] is the y'th element
- *  @param z Z data source. z[ofs_z*n] is the z'th element
- *
- *  @note The data arrays must have storage for at least num+2 elements. Using
- *  this method is much faster than the 'other' NewellNormal()
- */
-template <int ofs_x, int ofs_y, int ofs_z, typename TReal>
-inline void NewellNormal (aiVector3t<TReal>& out, int num, TReal* x, TReal* y, TReal* z)
-{
-    // Duplicate the first two vertices at the end
-    x[(num+0)*ofs_x] = x[0];
-    x[(num+1)*ofs_x] = x[ofs_x];
-
-    y[(num+0)*ofs_y] = y[0];
-    y[(num+1)*ofs_y] = y[ofs_y];
-
-    z[(num+0)*ofs_z] = z[0];
-    z[(num+1)*ofs_z] = z[ofs_z];
-
-    TReal sum_xy = 0.0, sum_yz = 0.0, sum_zx = 0.0;
-
-    TReal *xptr = x +ofs_x, *xlow = x, *xhigh = x + ofs_x*2;
-    TReal *yptr = y +ofs_y, *ylow = y, *yhigh = y + ofs_y*2;
-    TReal *zptr = z +ofs_z, *zlow = z, *zhigh = z + ofs_z*2;
-
-    for (int tmp=0; tmp < num; tmp++) {
-        sum_xy += (*xptr) * ( (*yhigh) - (*ylow) );
-        sum_yz += (*yptr) * ( (*zhigh) - (*zlow) );
-        sum_zx += (*zptr) * ( (*xhigh) - (*xlow) );
-
-        xptr  += ofs_x;
-        xlow  += ofs_x;
-        xhigh += ofs_x;
-
-        yptr  += ofs_y;
-        ylow  += ofs_y;
-        yhigh += ofs_y;
-
-        zptr  += ofs_z;
-        zlow  += ofs_z;
-        zhigh += ofs_z;
-    }
-    out = aiVector3t<TReal>(sum_yz,sum_zx,sum_xy);
-}
-
-} // ! Assimp
-
-#endif

+ 0 - 265
thirdparty/assimp/code/Common/PostStepRegistry.cpp

@@ -1,265 +0,0 @@
-/*
----------------------------------------------------------------------------
-Open Asset Import Library (assimp)
----------------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the following
-conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------------
-*/
-
-/** @file ImporterRegistry.cpp
-
-Central registry for all postprocessing steps available. Do not edit this file
-directly (unless you are adding new steps), instead use the
-corresponding preprocessor flag to selectively disable steps.
-*/
-
-#include "PostProcessing/ProcessHelper.h"
-
-#ifndef ASSIMP_BUILD_NO_CALCTANGENTS_PROCESS
-#   include "PostProcessing/CalcTangentsProcess.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_JOINVERTICES_PROCESS
-#   include "PostProcessing/JoinVerticesProcess.h"
-#endif
-#if !(defined ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS && defined ASSIMP_BUILD_NO_FLIPUVS_PROCESS && defined ASSIMP_BUILD_NO_FLIPWINDINGORDER_PROCESS)
-#   include "PostProcessing/ConvertToLHProcess.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_TRIANGULATE_PROCESS
-#   include "PostProcessing/TriangulateProcess.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_DROPFACENORMALS_PROCESS
-#   include "PostProcessing/DropFaceNormalsProcess.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_GENFACENORMALS_PROCESS
-#   include "PostProcessing/GenFaceNormalsProcess.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_GENVERTEXNORMALS_PROCESS
-#   include "PostProcessing/GenVertexNormalsProcess.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_REMOVEVC_PROCESS
-#   include "PostProcessing/RemoveVCProcess.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_SPLITLARGEMESHES_PROCESS
-#   include "PostProcessing/SplitLargeMeshes.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_PRETRANSFORMVERTICES_PROCESS
-#   include "PostProcessing/PretransformVertices.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_LIMITBONEWEIGHTS_PROCESS
-#   include "PostProcessing/LimitBoneWeightsProcess.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
-#   include "PostProcessing/ValidateDataStructure.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_IMPROVECACHELOCALITY_PROCESS
-#   include "PostProcessing/ImproveCacheLocality.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_FIXINFACINGNORMALS_PROCESS
-#   include "PostProcessing/FixNormalsStep.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_REMOVE_REDUNDANTMATERIALS_PROCESS
-#   include "PostProcessing/RemoveRedundantMaterials.h"
-#endif
-#if (!defined ASSIMP_BUILD_NO_EMBEDTEXTURES_PROCESS)
-#   include "PostProcessing/EmbedTexturesProcess.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_FINDINVALIDDATA_PROCESS
-#   include "PostProcessing/FindInvalidDataProcess.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_FINDDEGENERATES_PROCESS
-#   include "PostProcessing/FindDegenerates.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_SORTBYPTYPE_PROCESS
-#   include "PostProcessing/SortByPTypeProcess.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_GENUVCOORDS_PROCESS
-#   include "PostProcessing/ComputeUVMappingProcess.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_TRANSFORMTEXCOORDS_PROCESS
-#   include "PostProcessing/TextureTransform.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_FINDINSTANCES_PROCESS
-#   include "PostProcessing/FindInstancesProcess.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_OPTIMIZEMESHES_PROCESS
-#   include "PostProcessing/OptimizeMeshes.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_OPTIMIZEGRAPH_PROCESS
-#   include "PostProcessing/OptimizeGraph.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_SPLITBYBONECOUNT_PROCESS
-#   include "Common/SplitByBoneCountProcess.h"
-#endif
-#ifndef ASSIMP_BUILD_NO_DEBONE_PROCESS
-#   include "PostProcessing/DeboneProcess.h"
-#endif
-#if (!defined ASSIMP_BUILD_NO_GLOBALSCALE_PROCESS)
-#   include "PostProcessing/ScaleProcess.h"
-#endif
-#if (!defined ASSIMP_BUILD_NO_ARMATUREPOPULATE_PROCESS)
-#   include "PostProcessing/ArmaturePopulate.h"
-#endif
-#if (!defined ASSIMP_BUILD_NO_GENBOUNDINGBOXES_PROCESS)
-#   include "PostProcessing/GenBoundingBoxesProcess.h"
-#endif
-
-
-
-namespace Assimp {
-
-// ------------------------------------------------------------------------------------------------
-void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out)
-{
-    // ----------------------------------------------------------------------------
-    // Add an instance of each post processing step here in the order
-    // of sequence it is executed. Steps that are added here are not
-    // validated - as RegisterPPStep() does - all dependencies must be given.
-    // ----------------------------------------------------------------------------
-    out.reserve(31);
-#if (!defined ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS)
-    out.push_back( new MakeLeftHandedProcess());
-#endif
-#if (!defined ASSIMP_BUILD_NO_FLIPUVS_PROCESS)
-    out.push_back( new FlipUVsProcess());
-#endif
-#if (!defined ASSIMP_BUILD_NO_FLIPWINDINGORDER_PROCESS)
-    out.push_back( new FlipWindingOrderProcess());
-#endif
-#if (!defined ASSIMP_BUILD_NO_REMOVEVC_PROCESS)
-    out.push_back( new RemoveVCProcess());
-#endif
-#if (!defined ASSIMP_BUILD_NO_REMOVE_REDUNDANTMATERIALS_PROCESS)
-    out.push_back( new RemoveRedundantMatsProcess());
-#endif
-#if (!defined ASSIMP_BUILD_NO_EMBEDTEXTURES_PROCESS)
-    out.push_back( new EmbedTexturesProcess());
-#endif
-#if (!defined ASSIMP_BUILD_NO_FINDINSTANCES_PROCESS)
-    out.push_back( new FindInstancesProcess());
-#endif
-#if (!defined ASSIMP_BUILD_NO_OPTIMIZEGRAPH_PROCESS)
-    out.push_back( new OptimizeGraphProcess());
-#endif
-#ifndef ASSIMP_BUILD_NO_GENUVCOORDS_PROCESS
-    out.push_back( new ComputeUVMappingProcess());
-#endif
-#ifndef ASSIMP_BUILD_NO_TRANSFORMTEXCOORDS_PROCESS
-    out.push_back( new TextureTransformStep());
-#endif
-#if (!defined ASSIMP_BUILD_NO_GLOBALSCALE_PROCESS)
-    out.push_back( new ScaleProcess());
-#endif
-#if (!defined ASSIMP_BUILD_NO_ARMATUREPOPULATE_PROCESS)
-    out.push_back( new ArmaturePopulate());
-#endif
-#if (!defined ASSIMP_BUILD_NO_PRETRANSFORMVERTICES_PROCESS)
-    out.push_back( new PretransformVertices());
-#endif
-#if (!defined ASSIMP_BUILD_NO_TRIANGULATE_PROCESS)
-    out.push_back( new TriangulateProcess());
-#endif
-#if (!defined ASSIMP_BUILD_NO_FINDDEGENERATES_PROCESS)
-    //find degenerates should run after triangulation (to sort out small
-    //generated triangles) but before sort by p types (in case there are lines
-    //and points generated and inserted into a mesh)
-    out.push_back( new FindDegeneratesProcess());
-#endif
-#if (!defined ASSIMP_BUILD_NO_SORTBYPTYPE_PROCESS)
-    out.push_back( new SortByPTypeProcess());
-#endif
-#if (!defined ASSIMP_BUILD_NO_FINDINVALIDDATA_PROCESS)
-    out.push_back( new FindInvalidDataProcess());
-#endif
-#if (!defined ASSIMP_BUILD_NO_OPTIMIZEMESHES_PROCESS)
-    out.push_back( new OptimizeMeshesProcess());
-#endif
-#if (!defined ASSIMP_BUILD_NO_FIXINFACINGNORMALS_PROCESS)
-    out.push_back( new FixInfacingNormalsProcess());
-#endif
-#if (!defined ASSIMP_BUILD_NO_SPLITBYBONECOUNT_PROCESS)
-    out.push_back( new SplitByBoneCountProcess());
-#endif
-#if (!defined ASSIMP_BUILD_NO_SPLITLARGEMESHES_PROCESS)
-    out.push_back( new SplitLargeMeshesProcess_Triangle());
-#endif
-#if (!defined ASSIMP_BUILD_NO_GENFACENORMALS_PROCESS)
-    out.push_back( new DropFaceNormalsProcess());
-#endif
-#if (!defined ASSIMP_BUILD_NO_GENFACENORMALS_PROCESS)
-    out.push_back( new GenFaceNormalsProcess());
-#endif
-    // .........................................................................
-    // DON'T change the order of these five ..
-    // XXX this is actually a design weakness that dates back to the time
-    // when Importer would maintain the postprocessing step list exclusively.
-    // Now that others access it too, we need a better solution.
-    out.push_back( new ComputeSpatialSortProcess());
-    // .........................................................................
-
-#if (!defined ASSIMP_BUILD_NO_GENVERTEXNORMALS_PROCESS)
-    out.push_back( new GenVertexNormalsProcess());
-#endif
-#if (!defined ASSIMP_BUILD_NO_CALCTANGENTS_PROCESS)
-    out.push_back( new CalcTangentsProcess());
-#endif
-#if (!defined ASSIMP_BUILD_NO_JOINVERTICES_PROCESS)
-    out.push_back( new JoinVerticesProcess());
-#endif
-
-    // .........................................................................
-    out.push_back( new DestroySpatialSortProcess());
-    // .........................................................................
-
-#if (!defined ASSIMP_BUILD_NO_SPLITLARGEMESHES_PROCESS)
-    out.push_back( new SplitLargeMeshesProcess_Vertex());
-#endif
-#if (!defined ASSIMP_BUILD_NO_DEBONE_PROCESS)
-    out.push_back( new DeboneProcess());
-#endif
-#if (!defined ASSIMP_BUILD_NO_LIMITBONEWEIGHTS_PROCESS)
-    out.push_back( new LimitBoneWeightsProcess());
-#endif
-#if (!defined ASSIMP_BUILD_NO_IMPROVECACHELOCALITY_PROCESS)
-    out.push_back( new ImproveCacheLocalityProcess());
-#endif
-#if (!defined ASSIMP_BUILD_NO_GENBOUNDINGBOXES_PROCESS)
-    out.push_back(new GenBoundingBoxesProcess);
-#endif
-}
-
-}

+ 0 - 113
thirdparty/assimp/code/Common/RemoveComments.cpp

@@ -1,113 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file  RemoveComments.cpp
- *  @brief Defines the CommentRemover utility class
- */
-
-#include <assimp/RemoveComments.h>
-#include <assimp/ParsingUtils.h>
-
-namespace Assimp    {
-
-// ------------------------------------------------------------------------------------------------
-// Remove line comments from a file
-void CommentRemover::RemoveLineComments(const char* szComment,
-    char* szBuffer, char chReplacement /* = ' ' */)
-{
-    // validate parameters
-    ai_assert(NULL != szComment && NULL != szBuffer && *szComment);
-
-    const size_t len = strlen(szComment);
-    while (*szBuffer)   {
-
-        // skip over quotes
-        if (*szBuffer == '\"' || *szBuffer == '\'')
-            while (*szBuffer++ && *szBuffer != '\"' && *szBuffer != '\'');
-
-        if (!strncmp(szBuffer,szComment,len)) {
-            while (!IsLineEnd(*szBuffer))
-                *szBuffer++ = chReplacement;
-
-            if (!*szBuffer) {
-                break;
-            }
-        }
-        ++szBuffer;
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-// Remove multi-line comments from a file
-void CommentRemover::RemoveMultiLineComments(const char* szCommentStart,
-    const char* szCommentEnd,char* szBuffer,
-    char chReplacement)
-{
-    // validate parameters
-    ai_assert(NULL != szCommentStart && NULL != szCommentEnd &&
-        NULL != szBuffer && *szCommentStart && *szCommentEnd);
-
-    const size_t len  = strlen(szCommentEnd);
-    const size_t len2 = strlen(szCommentStart);
-
-    while (*szBuffer)   {
-        // skip over quotes
-        if (*szBuffer == '\"' || *szBuffer == '\'')
-            while (*szBuffer++ && *szBuffer != '\"' && *szBuffer != '\'');
-
-        if (!strncmp(szBuffer,szCommentStart,len2))  {
-            while (*szBuffer) {
-                if (!::strncmp(szBuffer,szCommentEnd,len)) {
-                    for (unsigned int i = 0; i < len;++i)
-                        *szBuffer++ = chReplacement;
-
-                    break;
-                }
-            *szBuffer++ = chReplacement;
-            }
-            continue;
-        }
-        ++szBuffer;
-    }
-}
-
-} // !! Assimp

+ 0 - 168
thirdparty/assimp/code/Common/SGSpatialSort.cpp

@@ -1,168 +0,0 @@
-/*
----------------------------------------------------------------------------
-Open Asset Import Library (assimp)
----------------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the following
-conditions are met:
-
-* Redistributions of source code must retain the above
-copyright notice, this list of conditions and the
-following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the
-following disclaimer in the documentation and/or other
-materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-contributors may be used to endorse or promote products
-derived from this software without specific prior
-written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------------
-*/
-
-/** @file Implementation of the helper class to quickly find
-vertices close to a given position. Special implementation for
-the 3ds loader handling smooth groups correctly  */
-
-#include <assimp/SGSpatialSort.h>
-
-using namespace Assimp;
-
-// ------------------------------------------------------------------------------------------------
-SGSpatialSort::SGSpatialSort()
-{
-    // define the reference plane. We choose some arbitrary vector away from all basic axises
-    // in the hope that no model spreads all its vertices along this plane.
-    mPlaneNormal.Set( 0.8523f, 0.34321f, 0.5736f);
-    mPlaneNormal.Normalize();
-}
-// ------------------------------------------------------------------------------------------------
-// Destructor
-SGSpatialSort::~SGSpatialSort()
-{
-    // nothing to do here, everything destructs automatically
-}
-// ------------------------------------------------------------------------------------------------
-void SGSpatialSort::Add(const aiVector3D& vPosition, unsigned int index,
-    unsigned int smoothingGroup)
-{
-    // store position by index and distance
-    float distance = vPosition * mPlaneNormal;
-    mPositions.push_back( Entry( index, vPosition,
-        distance, smoothingGroup));
-}
-// ------------------------------------------------------------------------------------------------
-void SGSpatialSort::Prepare()
-{
-    // now sort the array ascending by distance.
-    std::sort( this->mPositions.begin(), this->mPositions.end());
-}
-// ------------------------------------------------------------------------------------------------
-// Returns an iterator for all positions close to the given position.
-void SGSpatialSort::FindPositions( const aiVector3D& pPosition,
-    uint32_t pSG,
-    float pRadius,
-    std::vector<unsigned int>& poResults,
-    bool exactMatch /*= false*/) const
-{
-    float dist = pPosition * mPlaneNormal;
-    float minDist = dist - pRadius, maxDist = dist + pRadius;
-
-    // clear the array
-    poResults.clear();
-
-    // quick check for positions outside the range
-    if( mPositions.empty() )
-        return;
-    if( maxDist < mPositions.front().mDistance)
-        return;
-    if( minDist > mPositions.back().mDistance)
-        return;
-
-    // do a binary search for the minimal distance to start the iteration there
-    unsigned int index = (unsigned int)mPositions.size() / 2;
-    unsigned int binaryStepSize = (unsigned int)mPositions.size() / 4;
-    while( binaryStepSize > 1)
-    {
-        if( mPositions[index].mDistance < minDist)
-            index += binaryStepSize;
-        else
-            index -= binaryStepSize;
-
-        binaryStepSize /= 2;
-    }
-
-    // depending on the direction of the last step we need to single step a bit back or forth
-    // to find the actual beginning element of the range
-    while( index > 0 && mPositions[index].mDistance > minDist)
-        index--;
-    while( index < (mPositions.size() - 1) && mPositions[index].mDistance < minDist)
-        index++;
-
-    // Mow start iterating from there until the first position lays outside of the distance range.
-    // Add all positions inside the distance range within the given radius to the result aray
-
-    float squareEpsilon = pRadius * pRadius;
-    std::vector<Entry>::const_iterator it  = mPositions.begin() + index;
-    std::vector<Entry>::const_iterator end = mPositions.end();
-
-    if (exactMatch)
-    {
-        while( it->mDistance < maxDist)
-        {
-            if((it->mPosition - pPosition).SquareLength() < squareEpsilon && it->mSmoothGroups == pSG)
-            {
-                poResults.push_back( it->mIndex);
-            }
-            ++it;
-            if( end == it )break;
-        }
-    }
-    else
-    {
-        // if the given smoothing group is 0, we'll return all surrounding vertices
-        if (!pSG)
-        {
-            while( it->mDistance < maxDist)
-            {
-                if((it->mPosition - pPosition).SquareLength() < squareEpsilon)
-                    poResults.push_back( it->mIndex);
-                ++it;
-                if( end == it)break;
-            }
-        }
-        else while( it->mDistance < maxDist)
-        {
-            if((it->mPosition - pPosition).SquareLength() < squareEpsilon &&
-                (it->mSmoothGroups & pSG || !it->mSmoothGroups))
-            {
-                poResults.push_back( it->mIndex);
-            }
-            ++it;
-            if( end == it)break;
-        }
-    }
-}
-
-

+ 0 - 1350
thirdparty/assimp/code/Common/SceneCombiner.cpp

@@ -1,1350 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, 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.
-
-----------------------------------------------------------------------
-*/
-
-// TODO: refactor entire file to get rid of the "flat-copy" first approach
-// to copying structures. This easily breaks in the most unintuitive way
-// possible as new fields are added to assimp structures.
-
-// ----------------------------------------------------------------------------
-/** 
-  * @file Implements Assimp::SceneCombiner. This is a smart utility
-  *       class that combines multiple scenes, meshes, ... into one. Currently
-  *       these utilities are used by the IRR and LWS loaders and the
-  *       OptimizeGraph step.
-  */
-// ----------------------------------------------------------------------------
-#include <assimp/SceneCombiner.h>
-#include <assimp/StringUtils.h>
-#include <assimp/fast_atof.h>
-#include <assimp/metadata.h>
-#include <assimp/Hash.h>
-#include "time.h"
-#include <assimp/DefaultLogger.hpp>
-#include <assimp/scene.h>
-#include <assimp/mesh.h>
-#include <stdio.h>
-#include "ScenePrivate.h"
-
-namespace Assimp {
-
-// ------------------------------------------------------------------------------------------------
-// Add a prefix to a string
-inline
-void PrefixString(aiString& string,const char* prefix, unsigned int len) {
-    // If the string is already prefixed, we won't prefix it a second time
-    if (string.length >= 1 && string.data[0] == '$')
-        return;
-
-    if (len+string.length>=MAXLEN-1) {
-        ASSIMP_LOG_DEBUG("Can't add an unique prefix because the string is too long");
-        ai_assert(false);
-        return;
-    }
-
-    // Add the prefix
-    ::memmove(string.data+len,string.data,string.length+1);
-    ::memcpy (string.data, prefix, len);
-
-    // And update the string's length
-    string.length += len;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Add node identifiers to a hashing set
-void SceneCombiner::AddNodeHashes(aiNode* node, std::set<unsigned int>& hashes) {
-    // Add node name to hashing set if it is non-empty - empty nodes are allowed
-    // and they can't have any anims assigned so its absolutely safe to duplicate them.
-    if (node->mName.length) {
-        hashes.insert( SuperFastHash(node->mName.data, static_cast<uint32_t>(node->mName.length)) );
-    }
-
-    // Process all children recursively
-    for (unsigned int i = 0; i < node->mNumChildren;++i)
-        AddNodeHashes(node->mChildren[i],hashes);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Add a name prefix to all nodes in a hierarchy
-void SceneCombiner::AddNodePrefixes(aiNode* node, const char* prefix, unsigned int len) {
-    ai_assert(NULL != prefix);
-    PrefixString(node->mName,prefix,len);
-
-    // Process all children recursively
-    for ( unsigned int i = 0; i < node->mNumChildren; ++i ) {
-        AddNodePrefixes( node->mChildren[ i ], prefix, len );
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-// Search for matching names
-bool SceneCombiner::FindNameMatch(const aiString& name, std::vector<SceneHelper>& input, unsigned int cur) {
-    const unsigned int hash = SuperFastHash(name.data, static_cast<uint32_t>(name.length));
-
-    // Check whether we find a positive match in one of the given sets
-    for (unsigned int i = 0; i < input.size(); ++i) {
-        if (cur != i && input[i].hashes.find(hash) != input[i].hashes.end()) {
-            return true;
-        }
-    }
-    return false;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Add a name prefix to all nodes in a hierarchy if a hash match is found
-void SceneCombiner::AddNodePrefixesChecked(aiNode* node, const char* prefix, unsigned int len,
-        std::vector<SceneHelper>& input, unsigned int cur) {
-    ai_assert(NULL != prefix);
-    const unsigned int hash = SuperFastHash(node->mName.data, static_cast<uint32_t>(node->mName.length));
-
-    // Check whether we find a positive match in one of the given sets
-    for (unsigned int i = 0; i < input.size(); ++i) {
-        if (cur != i && input[i].hashes.find(hash) != input[i].hashes.end()) {
-            PrefixString(node->mName,prefix,len);
-            break;
-        }
-    }
-
-    // Process all children recursively
-    for (unsigned int i = 0; i < node->mNumChildren;++i)
-        AddNodePrefixesChecked(node->mChildren[i],prefix,len,input,cur);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Add an offset to all mesh indices in a node graph
-void SceneCombiner::OffsetNodeMeshIndices (aiNode* node, unsigned int offset) {
-    for (unsigned int i = 0; i < node->mNumMeshes;++i)
-        node->mMeshes[i] += offset;
-
-    for ( unsigned int i = 0; i < node->mNumChildren; ++i ) {
-        OffsetNodeMeshIndices( node->mChildren[ i ], offset );
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-// Merges two scenes. Currently only used by the LWS loader.
-void SceneCombiner::MergeScenes(aiScene** _dest,std::vector<aiScene*>& src, unsigned int flags) {
-    if ( nullptr == _dest ) {
-        return;
-    }
-
-    // if _dest points to NULL allocate a new scene. Otherwise clear the old and reuse it
-    if (src.empty()) {
-        if (*_dest) {
-            (*_dest)->~aiScene();
-            SceneCombiner::CopySceneFlat(_dest,src[0]);
-        }
-        else *_dest = src[0];
-        return;
-    }
-    if (*_dest)(*_dest)->~aiScene();
-    else *_dest = new aiScene();
-
-    // Create a dummy scene to serve as master for the others
-    aiScene* master = new aiScene();
-    master->mRootNode = new aiNode();
-    master->mRootNode->mName.Set("<MergeRoot>");
-
-    std::vector<AttachmentInfo> srcList (src.size());
-    for (unsigned int i = 0; i < srcList.size();++i)    {
-        srcList[i] = AttachmentInfo(src[i],master->mRootNode);
-    }
-
-    // 'master' will be deleted afterwards
-    MergeScenes (_dest, master, srcList, flags);
-}
-
-// ------------------------------------------------------------------------------------------------
-void SceneCombiner::AttachToGraph (aiNode* attach, std::vector<NodeAttachmentInfo>& srcList) {
-    unsigned int cnt;
-    for ( cnt = 0; cnt < attach->mNumChildren; ++cnt ) {
-        AttachToGraph( attach->mChildren[ cnt ], srcList );
-    }
-
-    cnt = 0;
-    for (std::vector<NodeAttachmentInfo>::iterator it = srcList.begin();
-         it != srcList.end(); ++it)
-    {
-        if ((*it).attachToNode == attach && !(*it).resolved)
-            ++cnt;
-    }
-
-    if (cnt)    {
-        aiNode** n = new aiNode*[cnt+attach->mNumChildren];
-        if (attach->mNumChildren)   {
-            ::memcpy(n,attach->mChildren,sizeof(void*)*attach->mNumChildren);
-            delete[] attach->mChildren;
-        }
-        attach->mChildren = n;
-
-        n += attach->mNumChildren;
-        attach->mNumChildren += cnt;
-
-        for (unsigned int i = 0; i < srcList.size();++i)    {
-            NodeAttachmentInfo& att = srcList[i];
-            if (att.attachToNode == attach && !att.resolved)    {
-                *n = att.node;
-                (**n).mParent = attach;
-                ++n;
-
-                // mark this attachment as resolved
-                att.resolved = true;
-            }
-        }
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-void SceneCombiner::AttachToGraph ( aiScene* master, std::vector<NodeAttachmentInfo>& src) {
-    ai_assert(NULL != master);
-    AttachToGraph(master->mRootNode,src);
-}
-
-// ------------------------------------------------------------------------------------------------
-void SceneCombiner::MergeScenes(aiScene** _dest, aiScene* master, std::vector<AttachmentInfo>& srcList, unsigned int flags) {
-    if ( nullptr == _dest ) {
-        return;
-    }
-
-    // if _dest points to NULL allocate a new scene. Otherwise clear the old and reuse it
-    if (srcList.empty())    {
-        if (*_dest) {
-            SceneCombiner::CopySceneFlat(_dest,master);
-        }
-        else *_dest = master;
-        return;
-    }
-    if (*_dest) {
-        (*_dest)->~aiScene();
-        new (*_dest) aiScene();
-    }
-    else *_dest = new aiScene();
-
-    aiScene* dest = *_dest;
-
-    std::vector<SceneHelper> src (srcList.size()+1);
-    src[0].scene = master;
-    for (unsigned int i = 0; i < srcList.size();++i)    {
-        src[i+1] = SceneHelper( srcList[i].scene );
-    }
-
-    // this helper array specifies which scenes are duplicates of others
-    std::vector<unsigned int> duplicates(src.size(),UINT_MAX);
-
-    // this helper array is used as lookup table several times
-    std::vector<unsigned int> offset(src.size());
-
-    // Find duplicate scenes
-    for (unsigned int i = 0; i < src.size();++i) {
-        if (duplicates[i] != i && duplicates[i] != UINT_MAX) {
-            continue;
-        }
-
-        duplicates[i] = i;
-        for ( unsigned int a = i+1; a < src.size(); ++a)    {
-            if (src[i].scene == src[a].scene) {
-                duplicates[a] = i;
-            }
-        }
-    }
-
-    // Generate unique names for all named stuff?
-    if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES)
-    {
-#if 0
-        // Construct a proper random number generator
-        boost::mt19937 rng(  );
-        boost::uniform_int<> dist(1u,1 << 24u);
-        boost::variate_generator<boost::mt19937&, boost::uniform_int<> > rndGen(rng, dist);
-#endif
-        for (unsigned int i = 1; i < src.size();++i)
-        {
-            //if (i != duplicates[i])
-            //{
-            //  // duplicate scenes share the same UID
-            //  ::strcpy( src[i].id, src[duplicates[i]].id );
-            //  src[i].idlen = src[duplicates[i]].idlen;
-
-            //  continue;
-            //}
-
-            src[i].idlen = ai_snprintf(src[i].id, 32, "$%.6X$_",i);
-
-            if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY) {
-
-                // Compute hashes for all identifiers in this scene and store them
-                // in a sorted table (for convenience I'm using std::set). We hash
-                // just the node and animation channel names, all identifiers except
-                // the material names should be caught by doing this.
-                AddNodeHashes(src[i]->mRootNode,src[i].hashes);
-
-                for (unsigned int a = 0; a < src[i]->mNumAnimations;++a) {
-                    aiAnimation* anim = src[i]->mAnimations[a];
-                    src[i].hashes.insert(SuperFastHash(anim->mName.data,static_cast<uint32_t>(anim->mName.length)));
-                }
-            }
-        }
-    }
-
-    unsigned int cnt;
-
-    // First find out how large the respective output arrays must be
-    for ( unsigned int n = 0; n < src.size();++n )
-    {
-        SceneHelper* cur = &src[n];
-
-        if (n == duplicates[n] || flags & AI_INT_MERGE_SCENE_DUPLICATES_DEEP_CPY)   {
-            dest->mNumTextures   += (*cur)->mNumTextures;
-            dest->mNumMaterials  += (*cur)->mNumMaterials;
-            dest->mNumMeshes     += (*cur)->mNumMeshes;
-        }
-
-        dest->mNumLights     += (*cur)->mNumLights;
-        dest->mNumCameras    += (*cur)->mNumCameras;
-        dest->mNumAnimations += (*cur)->mNumAnimations;
-
-        // Combine the flags of all scenes
-        // We need to process them flag-by-flag here to get correct results
-        // dest->mFlags ; //|= (*cur)->mFlags;
-        if ((*cur)->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) {
-            dest->mFlags |= AI_SCENE_FLAGS_NON_VERBOSE_FORMAT;
-        }
-    }
-
-    // generate the output texture list + an offset table for all texture indices
-    if (dest->mNumTextures)
-    {
-        aiTexture** pip = dest->mTextures = new aiTexture*[dest->mNumMaterials];
-        cnt = 0;
-        for ( unsigned int n = 0; n < src.size();++n )
-        {
-            SceneHelper* cur = &src[n];
-            for (unsigned int i = 0; i < (*cur)->mNumTextures;++i)
-            {
-                if (n != duplicates[n])
-                {
-                    if ( flags & AI_INT_MERGE_SCENE_DUPLICATES_DEEP_CPY)
-                        Copy(pip,(*cur)->mTextures[i]);
-
-                    else continue;
-                }
-                else *pip = (*cur)->mTextures[i];
-                ++pip;
-            }
-
-            offset[n] = cnt;
-            cnt = (unsigned int)(pip - dest->mTextures);
-        }
-    }
-
-    // generate the output material list + an offset table for all material indices
-    if (dest->mNumMaterials)
-    {
-        aiMaterial** pip = dest->mMaterials = new aiMaterial*[dest->mNumMaterials];
-        cnt = 0;
-        for ( unsigned int n = 0; n < src.size();++n )  {
-            SceneHelper* cur = &src[n];
-            for (unsigned int i = 0; i < (*cur)->mNumMaterials;++i)
-            {
-                if (n != duplicates[n])
-                {
-                    if ( flags & AI_INT_MERGE_SCENE_DUPLICATES_DEEP_CPY)
-                        Copy(pip,(*cur)->mMaterials[i]);
-
-                    else continue;
-                }
-                else *pip = (*cur)->mMaterials[i];
-
-                if ((*cur)->mNumTextures != dest->mNumTextures)     {
-                    // We need to update all texture indices of the mesh. So we need to search for
-                    // a material property called '$tex.file'
-
-                    for (unsigned int a = 0; a < (*pip)->mNumProperties;++a)
-                    {
-                        aiMaterialProperty* prop = (*pip)->mProperties[a];
-                        if (!strncmp(prop->mKey.data,"$tex.file",9))
-                        {
-                            // Check whether this texture is an embedded texture.
-                            // In this case the property looks like this: *<n>,
-                            // where n is the index of the texture.
-                            aiString& s = *((aiString*)prop->mData);
-                            if ('*' == s.data[0])   {
-                                // Offset the index and write it back ..
-                                const unsigned int idx = strtoul10(&s.data[1]) + offset[n];
-                                ASSIMP_itoa10(&s.data[1],sizeof(s.data)-1,idx);
-                            }
-                        }
-
-                        // Need to generate new, unique material names?
-                        else if (!::strcmp( prop->mKey.data,"$mat.name" ) && flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES)
-                        {
-                            aiString* pcSrc = (aiString*) prop->mData;
-                            PrefixString(*pcSrc, (*cur).id, (*cur).idlen);
-                        }
-                    }
-                }
-                ++pip;
-            }
-
-            offset[n] = cnt;
-            cnt = (unsigned int)(pip - dest->mMaterials);
-        }
-    }
-
-    // generate the output mesh list + again an offset table for all mesh indices
-    if (dest->mNumMeshes)
-    {
-        aiMesh** pip = dest->mMeshes = new aiMesh*[dest->mNumMeshes];
-        cnt = 0;
-        for ( unsigned int n = 0; n < src.size();++n )
-        {
-            SceneHelper* cur = &src[n];
-            for (unsigned int i = 0; i < (*cur)->mNumMeshes;++i)
-            {
-                if (n != duplicates[n]) {
-                    if ( flags & AI_INT_MERGE_SCENE_DUPLICATES_DEEP_CPY)
-                        Copy(pip, (*cur)->mMeshes[i]);
-
-                    else continue;
-                }
-                else *pip = (*cur)->mMeshes[i];
-
-                // update the material index of the mesh
-                (*pip)->mMaterialIndex +=  offset[n];
-                ++pip;
-            }
-
-            // reuse the offset array - store now the mesh offset in it
-            offset[n] = cnt;
-            cnt = (unsigned int)(pip - dest->mMeshes);
-        }
-    }
-
-    std::vector <NodeAttachmentInfo> nodes;
-    nodes.reserve(srcList.size());
-
-    // ----------------------------------------------------------------------------
-    // Now generate the output node graph. We need to make those
-    // names in the graph that are referenced by anims or lights
-    // or cameras unique. So we add a prefix to them ... $<rand>_
-    // We could also use a counter, but using a random value allows us to
-    // use just one prefix if we are joining multiple scene hierarchies recursively.
-    // Chances are quite good we don't collide, so we try that ...
-    // ----------------------------------------------------------------------------
-
-    // Allocate space for light sources, cameras and animations
-    aiLight** ppLights = dest->mLights = (dest->mNumLights
-        ? new aiLight*[dest->mNumLights] : NULL);
-
-    aiCamera** ppCameras = dest->mCameras = (dest->mNumCameras
-        ? new aiCamera*[dest->mNumCameras] : NULL);
-
-    aiAnimation** ppAnims = dest->mAnimations = (dest->mNumAnimations
-        ? new aiAnimation*[dest->mNumAnimations] : NULL);
-
-    for ( int n = static_cast<int>(src.size()-1); n >= 0 ;--n ) /* !!! important !!! */
-    {
-        SceneHelper* cur = &src[n];
-        aiNode* node;
-
-        // To offset or not to offset, this is the question
-        if (n != (int)duplicates[n])
-        {
-            // Get full scene-graph copy
-            Copy( &node, (*cur)->mRootNode );
-            OffsetNodeMeshIndices(node,offset[duplicates[n]]);
-
-            if (flags & AI_INT_MERGE_SCENE_DUPLICATES_DEEP_CPY) {
-                // (note:) they are already 'offseted' by offset[duplicates[n]]
-                OffsetNodeMeshIndices(node,offset[n] - offset[duplicates[n]]);
-            }
-        }
-        else // if (n == duplicates[n])
-        {
-            node = (*cur)->mRootNode;
-            OffsetNodeMeshIndices(node,offset[n]);
-        }
-        if (n) // src[0] is the master node
-            nodes.push_back(NodeAttachmentInfo( node,srcList[n-1].attachToNode,n ));
-
-        // add name prefixes?
-        if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES) {
-
-            // or the whole scenegraph
-            if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY) {
-                AddNodePrefixesChecked(node,(*cur).id,(*cur).idlen,src,n);
-            }
-            else AddNodePrefixes(node,(*cur).id,(*cur).idlen);
-
-            // meshes
-            for (unsigned int i = 0; i < (*cur)->mNumMeshes;++i)    {
-                aiMesh* mesh = (*cur)->mMeshes[i];
-
-                // rename all bones
-                for (unsigned int a = 0; a < mesh->mNumBones;++a)   {
-                    if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY) {
-                        if (!FindNameMatch(mesh->mBones[a]->mName,src,n))
-                            continue;
-                    }
-                    PrefixString(mesh->mBones[a]->mName,(*cur).id,(*cur).idlen);
-                }
-            }
-        }
-
-        // --------------------------------------------------------------------
-        // Copy light sources
-        for (unsigned int i = 0; i < (*cur)->mNumLights;++i,++ppLights)
-        {
-            if (n != (int)duplicates[n]) // duplicate scene?
-            {
-                Copy(ppLights, (*cur)->mLights[i]);
-            }
-            else *ppLights = (*cur)->mLights[i];
-
-
-            // Add name prefixes?
-            if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES) {
-                if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY) {
-                    if (!FindNameMatch((*ppLights)->mName,src,n))
-                        continue;
-                }
-
-                PrefixString((*ppLights)->mName,(*cur).id,(*cur).idlen);
-            }
-        }
-
-        // --------------------------------------------------------------------
-        // Copy cameras
-        for (unsigned int i = 0; i < (*cur)->mNumCameras;++i,++ppCameras)   {
-            if (n != (int)duplicates[n]) // duplicate scene?
-            {
-                Copy(ppCameras, (*cur)->mCameras[i]);
-            }
-            else *ppCameras = (*cur)->mCameras[i];
-
-            // Add name prefixes?
-            if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES) {
-                if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY) {
-                    if (!FindNameMatch((*ppCameras)->mName,src,n))
-                        continue;
-                }
-
-                PrefixString((*ppCameras)->mName,(*cur).id,(*cur).idlen);
-            }
-        }
-
-        // --------------------------------------------------------------------
-        // Copy animations
-        for (unsigned int i = 0; i < (*cur)->mNumAnimations;++i,++ppAnims)  {
-            if (n != (int)duplicates[n]) // duplicate scene?
-            {
-                Copy(ppAnims, (*cur)->mAnimations[i]);
-            }
-            else *ppAnims = (*cur)->mAnimations[i];
-
-            // Add name prefixes?
-            if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES) {
-                if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY) {
-                    if (!FindNameMatch((*ppAnims)->mName,src,n))
-                        continue;
-                }
-
-                PrefixString((*ppAnims)->mName,(*cur).id,(*cur).idlen);
-
-                // don't forget to update all node animation channels
-                for (unsigned int a = 0; a < (*ppAnims)->mNumChannels;++a) {
-                    if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY) {
-                        if (!FindNameMatch((*ppAnims)->mChannels[a]->mNodeName,src,n))
-                            continue;
-                    }
-
-                    PrefixString((*ppAnims)->mChannels[a]->mNodeName,(*cur).id,(*cur).idlen);
-                }
-            }
-        }
-    }
-
-    // Now build the output graph
-    AttachToGraph ( master, nodes);
-    dest->mRootNode = master->mRootNode;
-
-    // Check whether we succeeded at building the output graph
-    for (std::vector <NodeAttachmentInfo> ::iterator it = nodes.begin();
-        it != nodes.end(); ++it)
-    {
-        if (!(*it).resolved) {
-            if (flags & AI_INT_MERGE_SCENE_RESOLVE_CROSS_ATTACHMENTS) {
-                // search for this attachment point in all other imported scenes, too.
-                for ( unsigned int n = 0; n < src.size();++n ) {
-                    if (n != (*it).src_idx) {
-                        AttachToGraph(src[n].scene,nodes);
-                        if ((*it).resolved)
-                            break;
-                    }
-                }
-            }
-            if (!(*it).resolved) {
-                ASSIMP_LOG_ERROR_F( "SceneCombiner: Failed to resolve attachment ", (*it).node->mName.data,
-                    " ", (*it).attachToNode->mName.data );
-            }
-        }
-    }
-
-    // now delete all input scenes. Make sure duplicate scenes aren't
-    // deleted more than one time
-    for ( unsigned int n = 0; n < src.size();++n )  {
-        if (n != duplicates[n]) // duplicate scene?
-            continue;
-
-        aiScene* deleteMe = src[n].scene;
-
-        // We need to delete the arrays before the destructor is called -
-        // we are reusing the array members
-        delete[] deleteMe->mMeshes;     deleteMe->mMeshes     = NULL;
-        delete[] deleteMe->mCameras;    deleteMe->mCameras    = NULL;
-        delete[] deleteMe->mLights;     deleteMe->mLights     = NULL;
-        delete[] deleteMe->mMaterials;  deleteMe->mMaterials  = NULL;
-        delete[] deleteMe->mAnimations; deleteMe->mAnimations = NULL;
-
-        deleteMe->mRootNode = NULL;
-
-        // Now we can safely delete the scene
-        delete deleteMe;
-    }
-
-    // Check flags
-    if (!dest->mNumMeshes || !dest->mNumMaterials) {
-        dest->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
-    }
-
-    // We're finished
-}
-
-// ------------------------------------------------------------------------------------------------
-// Build a list of unique bones
-void SceneCombiner::BuildUniqueBoneList(std::list<BoneWithHash>& asBones,
-    std::vector<aiMesh*>::const_iterator it,
-    std::vector<aiMesh*>::const_iterator end)
-{
-    unsigned int iOffset = 0;
-    for (; it != end;++it)  {
-        for (unsigned int l = 0; l < (*it)->mNumBones;++l)  {
-            aiBone* p = (*it)->mBones[l];
-            uint32_t itml = SuperFastHash(p->mName.data,(unsigned int)p->mName.length);
-
-            std::list<BoneWithHash>::iterator it2  = asBones.begin();
-            std::list<BoneWithHash>::iterator end2 = asBones.end();
-
-            for (;it2 != end2;++it2)    {
-                if ((*it2).first == itml)   {
-                    (*it2).pSrcBones.push_back(BoneSrcIndex(p,iOffset));
-                    break;
-                }
-            }
-            if (end2 == it2)    {
-                // need to begin a new bone entry
-                asBones.push_back(BoneWithHash());
-                BoneWithHash& btz = asBones.back();
-
-                // setup members
-                btz.first = itml;
-                btz.second = &p->mName;
-                btz.pSrcBones.push_back(BoneSrcIndex(p,iOffset));
-            }
-        }
-        iOffset += (*it)->mNumVertices;
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-// Merge a list of bones
-void SceneCombiner::MergeBones(aiMesh* out,std::vector<aiMesh*>::const_iterator it,
-    std::vector<aiMesh*>::const_iterator end)
-{
-    if ( nullptr == out || out->mNumBones == 0 ) {
-        return;
-    }
-
-    // find we need to build an unique list of all bones.
-    // we work with hashes to make the comparisons MUCH faster,
-    // at least if we have many bones.
-    std::list<BoneWithHash> asBones;
-    BuildUniqueBoneList( asBones, it, end );
-
-    // now create the output bones
-    out->mNumBones = 0;
-    out->mBones = new aiBone*[asBones.size()];
-
-    for (std::list<BoneWithHash>::const_iterator boneIt = asBones.begin(),boneEnd = asBones.end(); boneIt != boneEnd; ++boneIt )  {
-        // Allocate a bone and setup it's name
-        aiBone* pc = out->mBones[out->mNumBones++] = new aiBone();
-        pc->mName = aiString( *( boneIt->second ));
-
-        std::vector< BoneSrcIndex >::const_iterator wend = boneIt->pSrcBones.end();
-
-        // Loop through all bones to be joined for this bone
-        for (std::vector< BoneSrcIndex >::const_iterator wmit = boneIt->pSrcBones.begin(); wmit != wend; ++wmit)  {
-            pc->mNumWeights += (*wmit).first->mNumWeights;
-
-            // NOTE: different offset matrices for bones with equal names
-            // are - at the moment - not handled correctly.
-            if (wmit != boneIt->pSrcBones.begin() && pc->mOffsetMatrix != wmit->first->mOffsetMatrix) {
-                ASSIMP_LOG_WARN("Bones with equal names but different offset matrices can't be joined at the moment");
-                continue;
-            }
-            pc->mOffsetMatrix = wmit->first->mOffsetMatrix;
-        }
-
-        // Allocate the vertex weight array
-        aiVertexWeight* avw = pc->mWeights = new aiVertexWeight[pc->mNumWeights];
-
-        // And copy the final weights - adjust the vertex IDs by the
-        // face index offset of the corresponding mesh.
-        for (std::vector< BoneSrcIndex >::const_iterator wmit = (*boneIt).pSrcBones.begin(); wmit != (*boneIt).pSrcBones.end(); ++wmit) {
-            if (wmit == wend) {
-                break;
-            }
-
-            aiBone* pip = (*wmit).first;
-            for (unsigned int mp = 0; mp < pip->mNumWeights;++mp,++avw) {
-                const aiVertexWeight& vfi = pip->mWeights[mp];
-                avw->mWeight = vfi.mWeight;
-                avw->mVertexId = vfi.mVertexId + (*wmit).second;
-            }
-        }
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-// Merge a list of meshes
-void SceneCombiner::MergeMeshes(aiMesh** _out, unsigned int /*flags*/,
-    std::vector<aiMesh*>::const_iterator begin,
-    std::vector<aiMesh*>::const_iterator end)
-{
-    if ( nullptr == _out ) {
-        return;
-    }
-
-    if (begin == end)   {
-        *_out = NULL; // no meshes ...
-        return;
-    }
-
-    // Allocate the output mesh
-    aiMesh* out = *_out = new aiMesh();
-    out->mMaterialIndex = (*begin)->mMaterialIndex;
-
-    std::string name;
-    // Find out how much output storage we'll need
-    for (std::vector<aiMesh*>::const_iterator it = begin; it != end; ++it) {
-        const char *meshName( (*it)->mName.C_Str() );
-        name += std::string( meshName );
-        if ( it != end - 1 ) {
-            name += ".";
-        }
-        out->mNumVertices   += (*it)->mNumVertices;
-        out->mNumFaces      += (*it)->mNumFaces;
-        out->mNumBones      += (*it)->mNumBones;
-
-        // combine primitive type flags
-        out->mPrimitiveTypes |= (*it)->mPrimitiveTypes;
-    }
-    out->mName.Set( name.c_str() );
-
-    if (out->mNumVertices) {
-        aiVector3D* pv2;
-
-        // copy vertex positions
-        if ((**begin).HasPositions())   {
-
-            pv2 = out->mVertices = new aiVector3D[out->mNumVertices];
-            for (std::vector<aiMesh*>::const_iterator it = begin; it != end; ++it)  {
-                if ((*it)->mVertices)   {
-                    ::memcpy(pv2,(*it)->mVertices,(*it)->mNumVertices*sizeof(aiVector3D));
-                }
-                else ASSIMP_LOG_WARN("JoinMeshes: Positions expected but input mesh contains no positions");
-                pv2 += (*it)->mNumVertices;
-            }
-        }
-        // copy normals
-        if ((**begin).HasNormals()) {
-
-            pv2 = out->mNormals = new aiVector3D[out->mNumVertices];
-            for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it)   {
-                if ((*it)->mNormals)    {
-                    ::memcpy(pv2,(*it)->mNormals,(*it)->mNumVertices*sizeof(aiVector3D));
-                } else {
-                    ASSIMP_LOG_WARN( "JoinMeshes: Normals expected but input mesh contains no normals" );
-                }
-                pv2 += (*it)->mNumVertices;
-            }
-        }
-        // copy tangents and bi-tangents
-        if ((**begin).HasTangentsAndBitangents())   {
-
-            pv2 = out->mTangents = new aiVector3D[out->mNumVertices];
-            aiVector3D* pv2b = out->mBitangents = new aiVector3D[out->mNumVertices];
-
-            for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) {
-                if ((*it)->mTangents)   {
-                    ::memcpy(pv2, (*it)->mTangents,  (*it)->mNumVertices*sizeof(aiVector3D));
-                    ::memcpy(pv2b,(*it)->mBitangents,(*it)->mNumVertices*sizeof(aiVector3D));
-                } else {
-                    ASSIMP_LOG_WARN( "JoinMeshes: Tangents expected but input mesh contains no tangents" );
-                }
-                pv2  += (*it)->mNumVertices;
-                pv2b += (*it)->mNumVertices;
-            }
-        }
-        // copy texture coordinates
-        unsigned int n = 0;
-        while ((**begin).HasTextureCoords(n)) {
-            out->mNumUVComponents[n] = (*begin)->mNumUVComponents[n];
-
-            pv2 = out->mTextureCoords[n] = new aiVector3D[out->mNumVertices];
-            for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it)   {
-                if ((*it)->mTextureCoords[n])   {
-                    ::memcpy(pv2,(*it)->mTextureCoords[n],(*it)->mNumVertices*sizeof(aiVector3D));
-                } else {
-                    ASSIMP_LOG_WARN( "JoinMeshes: UVs expected but input mesh contains no UVs" );
-                }
-                pv2 += (*it)->mNumVertices;
-            }
-            ++n;
-        }
-        // copy vertex colors
-        n = 0;
-        while ((**begin).HasVertexColors(n))    {
-            aiColor4D *pVec2 = out->mColors[n] = new aiColor4D[out->mNumVertices];
-            for ( std::vector<aiMesh*>::const_iterator it = begin; it != end; ++it )   {
-                if ((*it)->mColors[n])  {
-                    ::memcpy( pVec2, (*it)->mColors[ n ], (*it)->mNumVertices * sizeof( aiColor4D ) ) ;
-                } else {
-                    ASSIMP_LOG_WARN( "JoinMeshes: VCs expected but input mesh contains no VCs" );
-                }
-                pVec2 += (*it)->mNumVertices;
-            }
-            ++n;
-        }
-    }
-
-    if (out->mNumFaces) // just for safety
-    {
-        // copy faces
-        out->mFaces = new aiFace[out->mNumFaces];
-        aiFace* pf2 = out->mFaces;
-
-        unsigned int ofs = 0;
-        for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it)   {
-            for (unsigned int m = 0; m < (*it)->mNumFaces;++m,++pf2)    {
-                aiFace& face = (*it)->mFaces[m];
-                pf2->mNumIndices = face.mNumIndices;
-                pf2->mIndices = face.mIndices;
-
-                if (ofs)    {
-                    // add the offset to the vertex
-                    for (unsigned int q = 0; q < face.mNumIndices; ++q)
-                        face.mIndices[q] += ofs;
-                }
-                face.mIndices = NULL;
-            }
-            ofs += (*it)->mNumVertices;
-        }
-    }
-
-    // bones - as this is quite lengthy, I moved the code to a separate function
-    if (out->mNumBones)
-        MergeBones(out,begin,end);
-
-    // delete all source meshes
-    for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it)
-        delete *it;
-}
-
-// ------------------------------------------------------------------------------------------------
-void SceneCombiner::MergeMaterials(aiMaterial** dest,
-        std::vector<aiMaterial*>::const_iterator begin,
-        std::vector<aiMaterial*>::const_iterator end)
-{
-    if ( nullptr == dest ) {
-        return;
-    }
-
-    if (begin == end)   {
-        *dest = NULL; // no materials ...
-        return;
-    }
-
-    // Allocate the output material
-    aiMaterial* out = *dest = new aiMaterial();
-
-    // Get the maximal number of properties
-    unsigned int size = 0;
-    for (std::vector<aiMaterial*>::const_iterator it = begin; it != end; ++it) {
-        size += (*it)->mNumProperties;
-    }
-
-    out->Clear();
-    delete[] out->mProperties;
-
-    out->mNumAllocated = size;
-    out->mNumProperties = 0;
-    out->mProperties = new aiMaterialProperty*[out->mNumAllocated];
-
-    for (std::vector<aiMaterial*>::const_iterator it = begin; it != end; ++it) {
-        for(unsigned int i = 0; i < (*it)->mNumProperties; ++i) {
-            aiMaterialProperty* sprop = (*it)->mProperties[i];
-
-            // Test if we already have a matching property
-            const aiMaterialProperty* prop_exist;
-            if(aiGetMaterialProperty(out, sprop->mKey.C_Str(), sprop->mSemantic, sprop->mIndex, &prop_exist) != AI_SUCCESS) {
-                // If not, we add it to the new material
-                aiMaterialProperty* prop = out->mProperties[out->mNumProperties] = new aiMaterialProperty();
-
-                prop->mDataLength = sprop->mDataLength;
-                prop->mData = new char[prop->mDataLength];
-                ::memcpy(prop->mData, sprop->mData, prop->mDataLength);
-
-                prop->mIndex    = sprop->mIndex;
-                prop->mSemantic = sprop->mSemantic;
-                prop->mKey      = sprop->mKey;
-                prop->mType     = sprop->mType;
-
-                out->mNumProperties++;
-            }
-        }
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-template <typename Type>
-inline
-void CopyPtrArray (Type**& dest, const Type* const * src, ai_uint num) {
-    if (!num) {
-        dest = NULL;
-        return;
-    }
-    dest = new Type*[num];
-    for (ai_uint i = 0; i < num;++i) {
-        SceneCombiner::Copy(&dest[i],src[i]);
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-template <typename Type>
-inline
-void GetArrayCopy(Type*& dest, ai_uint num ) {
-    if ( !dest ) {
-        return;
-    }
-    Type* old = dest;
-
-    dest = new Type[num];
-    ::memcpy(dest, old, sizeof(Type) * num);
-}
-
-// ------------------------------------------------------------------------------------------------
-void SceneCombiner::CopySceneFlat(aiScene** _dest,const aiScene* src) {
-    if ( nullptr == _dest || nullptr == src ) {
-        return;
-    }
-
-    // reuse the old scene or allocate a new?
-    if (*_dest) {
-        (*_dest)->~aiScene();
-        new (*_dest) aiScene();
-    } else {
-        *_dest = new aiScene();
-    }
-
-    ::memcpy(*_dest,src,sizeof(aiScene));
-}
-
-// ------------------------------------------------------------------------------------------------
-void SceneCombiner::CopyScene(aiScene** _dest,const aiScene* src,bool allocate) {
-    if ( nullptr == _dest || nullptr == src ) {
-        return;
-    }
-
-    if (allocate) {
-        *_dest = new aiScene();
-    }
-    aiScene* dest = *_dest;
-    ai_assert(nullptr != dest);
-
-    // copy metadata
-    if ( nullptr != src->mMetaData ) {
-        dest->mMetaData = new aiMetadata( *src->mMetaData );
-    }
-
-    // copy animations
-    dest->mNumAnimations = src->mNumAnimations;
-    CopyPtrArray(dest->mAnimations,src->mAnimations,
-        dest->mNumAnimations);
-
-    // copy textures
-    dest->mNumTextures = src->mNumTextures;
-    CopyPtrArray(dest->mTextures,src->mTextures,
-        dest->mNumTextures);
-
-    // copy materials
-    dest->mNumMaterials = src->mNumMaterials;
-    CopyPtrArray(dest->mMaterials,src->mMaterials,
-        dest->mNumMaterials);
-
-    // copy lights
-    dest->mNumLights = src->mNumLights;
-    CopyPtrArray(dest->mLights,src->mLights,
-        dest->mNumLights);
-
-    // copy cameras
-    dest->mNumCameras = src->mNumCameras;
-    CopyPtrArray(dest->mCameras,src->mCameras,
-        dest->mNumCameras);
-
-    // copy meshes
-    dest->mNumMeshes = src->mNumMeshes;
-    CopyPtrArray(dest->mMeshes,src->mMeshes,
-        dest->mNumMeshes);
-
-    // now - copy the root node of the scene (deep copy, too)
-    Copy( &dest->mRootNode, src->mRootNode);
-
-    // and keep the flags ...
-    dest->mFlags = src->mFlags;
-
-    // source private data might be NULL if the scene is user-allocated (i.e. for use with the export API)
-    if (dest->mPrivate != NULL) {
-        ScenePriv(dest)->mPPStepsApplied = ScenePriv(src) ? ScenePriv(src)->mPPStepsApplied : 0;
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-void SceneCombiner::Copy( aiMesh** _dest, const aiMesh* src ) {
-    if ( nullptr == _dest || nullptr == src ) {
-        return;
-    }
-
-    aiMesh* dest = *_dest = new aiMesh();
-
-    // get a flat copy
-    ::memcpy(dest,src,sizeof(aiMesh));
-
-    // and reallocate all arrays
-    GetArrayCopy( dest->mVertices,   dest->mNumVertices );
-    GetArrayCopy( dest->mNormals ,   dest->mNumVertices );
-    GetArrayCopy( dest->mTangents,   dest->mNumVertices );
-    GetArrayCopy( dest->mBitangents, dest->mNumVertices );
-
-    unsigned int n = 0;
-    while (dest->HasTextureCoords(n))
-        GetArrayCopy( dest->mTextureCoords[n++],   dest->mNumVertices );
-
-    n = 0;
-    while (dest->HasVertexColors(n))
-        GetArrayCopy( dest->mColors[n++],   dest->mNumVertices );
-
-    // make a deep copy of all bones
-    CopyPtrArray(dest->mBones,dest->mBones,dest->mNumBones);
-
-    // make a deep copy of all faces
-    GetArrayCopy(dest->mFaces,dest->mNumFaces);
-    for (unsigned int i = 0; i < dest->mNumFaces;++i) {
-        aiFace& f = dest->mFaces[i];
-        GetArrayCopy(f.mIndices,f.mNumIndices);
-    }
-
-    // make a deep copy of all blend shapes
-    CopyPtrArray(dest->mAnimMeshes, dest->mAnimMeshes, dest->mNumAnimMeshes);
-}
-
-// ------------------------------------------------------------------------------------------------
-void SceneCombiner::Copy(aiAnimMesh** _dest, const aiAnimMesh* src) {
-    if (nullptr == _dest || nullptr == src) {
-        return;
-    }
-
-    aiAnimMesh* dest = *_dest = new aiAnimMesh();
-
-    // get a flat copy
-    ::memcpy(dest, src, sizeof(aiAnimMesh));
-
-    // and reallocate all arrays
-    GetArrayCopy(dest->mVertices, dest->mNumVertices);
-    GetArrayCopy(dest->mNormals, dest->mNumVertices);
-    GetArrayCopy(dest->mTangents, dest->mNumVertices);
-    GetArrayCopy(dest->mBitangents, dest->mNumVertices);
-
-    unsigned int n = 0;
-    while (dest->HasTextureCoords(n))
-        GetArrayCopy(dest->mTextureCoords[n++], dest->mNumVertices);
-
-    n = 0;
-    while (dest->HasVertexColors(n))
-        GetArrayCopy(dest->mColors[n++], dest->mNumVertices);
-}
-
-// ------------------------------------------------------------------------------------------------
-void SceneCombiner::Copy (aiMaterial** _dest, const aiMaterial* src) {
-    if ( nullptr == _dest || nullptr == src ) {
-        return;
-    }
-
-    aiMaterial* dest = (aiMaterial*) ( *_dest = new aiMaterial() );
-
-    dest->Clear();
-    delete[] dest->mProperties;
-
-    dest->mNumAllocated  =  src->mNumAllocated;
-    dest->mNumProperties =  src->mNumProperties;
-    dest->mProperties    =  new aiMaterialProperty* [dest->mNumAllocated];
-
-    for (unsigned int i = 0; i < dest->mNumProperties;++i)
-    {
-        aiMaterialProperty* prop  = dest->mProperties[i] = new aiMaterialProperty();
-        aiMaterialProperty* sprop = src->mProperties[i];
-
-        prop->mDataLength = sprop->mDataLength;
-        prop->mData = new char[prop->mDataLength];
-        ::memcpy(prop->mData,sprop->mData,prop->mDataLength);
-
-        prop->mIndex    = sprop->mIndex;
-        prop->mSemantic = sprop->mSemantic;
-        prop->mKey      = sprop->mKey;
-        prop->mType     = sprop->mType;
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-void SceneCombiner::Copy(aiTexture** _dest, const aiTexture* src) {
-    if ( nullptr == _dest || nullptr == src ) {
-        return;
-    }
-
-    aiTexture* dest = *_dest = new aiTexture();
-
-    // get a flat copy
-    ::memcpy(dest,src,sizeof(aiTexture));
-
-    // and reallocate all arrays. We must do it manually here
-    const char* old = (const char*)dest->pcData;
-    if (old)
-    {
-        unsigned int cpy;
-        if (!dest->mHeight)cpy = dest->mWidth;
-        else cpy = dest->mHeight * dest->mWidth * sizeof(aiTexel);
-
-        if (!cpy)
-        {
-            dest->pcData = NULL;
-            return;
-        }
-        // the cast is legal, the aiTexel c'tor does nothing important
-        dest->pcData = (aiTexel*) new char[cpy];
-        ::memcpy(dest->pcData, old, cpy);
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-void SceneCombiner::Copy( aiAnimation** _dest, const aiAnimation* src ) {
-    if ( nullptr == _dest || nullptr == src ) {
-        return;
-    }
-
-    aiAnimation* dest = *_dest = new aiAnimation();
-
-    // get a flat copy
-    ::memcpy(dest,src,sizeof(aiAnimation));
-
-    // and reallocate all arrays
-    CopyPtrArray( dest->mChannels, src->mChannels, dest->mNumChannels );
-    CopyPtrArray( dest->mMorphMeshChannels, src->mMorphMeshChannels, dest->mNumMorphMeshChannels );
-}
-
-// ------------------------------------------------------------------------------------------------
-void SceneCombiner::Copy(aiNodeAnim** _dest, const aiNodeAnim* src) {
-    if ( nullptr == _dest || nullptr == src ) {
-        return;
-    }
-
-    aiNodeAnim* dest = *_dest = new aiNodeAnim();
-
-    // get a flat copy
-    ::memcpy(dest,src,sizeof(aiNodeAnim));
-
-    // and reallocate all arrays
-    GetArrayCopy( dest->mPositionKeys, dest->mNumPositionKeys );
-    GetArrayCopy( dest->mScalingKeys,  dest->mNumScalingKeys );
-    GetArrayCopy( dest->mRotationKeys, dest->mNumRotationKeys );
-}
-
-void SceneCombiner::Copy(aiMeshMorphAnim** _dest, const aiMeshMorphAnim* src) {
-    if ( nullptr == _dest || nullptr == src ) {
-        return;
-    }
-
-    aiMeshMorphAnim* dest = *_dest = new aiMeshMorphAnim();
-
-    // get a flat copy
-    ::memcpy(dest,src,sizeof(aiMeshMorphAnim));
-
-    // and reallocate all arrays
-    GetArrayCopy( dest->mKeys, dest->mNumKeys );
-    for (ai_uint i = 0; i < dest->mNumKeys;++i) {
-        dest->mKeys[i].mValues = new unsigned int[dest->mKeys[i].mNumValuesAndWeights];
-        dest->mKeys[i].mWeights = new double[dest->mKeys[i].mNumValuesAndWeights];
-        ::memcpy(dest->mKeys[i].mValues, src->mKeys[i].mValues, dest->mKeys[i].mNumValuesAndWeights * sizeof(unsigned int));
-        ::memcpy(dest->mKeys[i].mWeights, src->mKeys[i].mWeights, dest->mKeys[i].mNumValuesAndWeights * sizeof(double));
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-void SceneCombiner::Copy( aiCamera** _dest,const  aiCamera* src) {
-    if ( nullptr == _dest || nullptr == src ) {
-        return;
-    }
-
-    aiCamera* dest = *_dest = new aiCamera();
-
-    // get a flat copy, that's already OK
-    ::memcpy(dest,src,sizeof(aiCamera));
-}
-
-// ------------------------------------------------------------------------------------------------
-void SceneCombiner::Copy(aiLight** _dest, const aiLight* src) {
-    if ( nullptr == _dest || nullptr == src ) {
-        return;
-    }
-
-    aiLight* dest = *_dest = new aiLight();
-
-    // get a flat copy, that's already OK
-    ::memcpy(dest,src,sizeof(aiLight));
-}
-
-// ------------------------------------------------------------------------------------------------
-void SceneCombiner::Copy(aiBone** _dest, const aiBone* src) {
-    if ( nullptr == _dest || nullptr == src ) {
-        return;
-    }
-
-    aiBone* dest = *_dest = new aiBone();
-
-    // get a flat copy
-    ::memcpy(dest,src,sizeof(aiBone));
-
-    // and reallocate all arrays
-    GetArrayCopy( dest->mWeights, dest->mNumWeights );
-}
-
-// ------------------------------------------------------------------------------------------------
-void SceneCombiner::Copy     (aiNode** _dest, const aiNode* src)
-{
-    ai_assert(NULL != _dest && NULL != src);
-
-    aiNode* dest = *_dest = new aiNode();
-
-    // get a flat copy
-    ::memcpy(dest,src,sizeof(aiNode));
-
-    if (src->mMetaData) {
-        Copy(&dest->mMetaData, src->mMetaData);
-    }
-
-    // and reallocate all arrays
-    GetArrayCopy( dest->mMeshes, dest->mNumMeshes );
-    CopyPtrArray( dest->mChildren, src->mChildren,dest->mNumChildren);
-
-	// need to set the mParent fields to the created aiNode.
-	for( unsigned int i = 0; i < dest->mNumChildren; i ++ ) {
-		dest->mChildren[i]->mParent = dest;
-	}
-}
-
-// ------------------------------------------------------------------------------------------------
-void SceneCombiner::Copy(aiMetadata** _dest, const aiMetadata* src) {
-    if ( nullptr == _dest || nullptr == src ) {
-        return;
-    }
-
-    if ( 0 == src->mNumProperties ) {
-        return;
-    }
-
-    aiMetadata* dest = *_dest = aiMetadata::Alloc( src->mNumProperties );
-    std::copy(src->mKeys, src->mKeys + src->mNumProperties, dest->mKeys);
-
-    dest->mValues = new aiMetadataEntry[src->mNumProperties];
-    for (unsigned int i = 0; i < src->mNumProperties; ++i) {
-        aiMetadataEntry& in = src->mValues[i];
-        aiMetadataEntry& out = dest->mValues[i];
-        out.mType = in.mType;
-        switch (dest->mValues[i].mType) {
-            case AI_BOOL:
-                out.mData = new bool(*static_cast<bool*>(in.mData));
-                break;
-            case AI_INT32:
-                out.mData = new int32_t(*static_cast<int32_t*>(in.mData));
-                break;
-            case AI_UINT64:
-                out.mData = new uint64_t(*static_cast<uint64_t*>(in.mData));
-                break;
-            case AI_FLOAT:
-                out.mData = new float(*static_cast<float*>(in.mData));
-                break;
-            case AI_DOUBLE:
-                out.mData = new double(*static_cast<double*>(in.mData));
-                break;
-            case AI_AISTRING:
-                out.mData = new aiString(*static_cast<aiString*>(in.mData));
-                break;
-            case AI_AIVECTOR3D:
-                out.mData = new aiVector3D(*static_cast<aiVector3D*>(in.mData));
-                break;
-            default:
-                ai_assert(false);
-                break;
-        }
-    }
-}
-
-} // Namespace Assimp
-

+ 0 - 261
thirdparty/assimp/code/Common/ScenePreprocessor.cpp

@@ -1,261 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, 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 "ScenePreprocessor.h"
-#include <assimp/ai_assert.h>
-#include <assimp/scene.h>
-#include <assimp/DefaultLogger.hpp>
-
-
-using namespace Assimp;
-
-// ---------------------------------------------------------------------------------------------
-void ScenePreprocessor::ProcessScene ()
-{
-    ai_assert(scene != NULL);
-
-    // Process all meshes
-    for (unsigned int i = 0; i < scene->mNumMeshes;++i)
-        ProcessMesh(scene->mMeshes[i]);
-
-    // - nothing to do for nodes for the moment
-    // - nothing to do for textures for the moment
-    // - nothing to do for lights for the moment
-    // - nothing to do for cameras for the moment
-
-    // Process all animations
-    for (unsigned int i = 0; i < scene->mNumAnimations;++i)
-        ProcessAnimation(scene->mAnimations[i]);
-
-    // Generate a default material if none was specified
-    if (!scene->mNumMaterials && scene->mNumMeshes) {
-        scene->mMaterials      = new aiMaterial*[2];
-        aiMaterial* helper;
-
-        aiString name;
-
-        scene->mMaterials[scene->mNumMaterials] = helper = new aiMaterial();
-        aiColor3D clr(0.6f,0.6f,0.6f);
-        helper->AddProperty(&clr,1,AI_MATKEY_COLOR_DIFFUSE);
-
-        // setup the default name to make this material identifiable
-        name.Set(AI_DEFAULT_MATERIAL_NAME);
-        helper->AddProperty(&name,AI_MATKEY_NAME);
-
-        ASSIMP_LOG_DEBUG("ScenePreprocessor: Adding default material \'" AI_DEFAULT_MATERIAL_NAME  "\'");
-
-        for (unsigned int i = 0; i < scene->mNumMeshes;++i) {
-            scene->mMeshes[i]->mMaterialIndex = scene->mNumMaterials;
-        }
-
-        scene->mNumMaterials++;
-    }
-}
-
-// ---------------------------------------------------------------------------------------------
-void ScenePreprocessor::ProcessMesh (aiMesh* mesh)
-{
-    // If aiMesh::mNumUVComponents is *not* set assign the default value of 2
-    for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i)   {
-        if (!mesh->mTextureCoords[i]) {
-            mesh->mNumUVComponents[i] = 0;
-        } else {
-            if (!mesh->mNumUVComponents[i])
-                mesh->mNumUVComponents[i] = 2;
-
-            aiVector3D* p = mesh->mTextureCoords[i], *end = p+mesh->mNumVertices;
-
-            // Ensure unused components are zeroed. This will make 1D texture channels work
-            // as if they were 2D channels .. just in case an application doesn't handle
-            // this case
-            if (2 == mesh->mNumUVComponents[i]) {
-                for (; p != end; ++p)
-                    p->z = 0.f;
-            }
-            else if (1 == mesh->mNumUVComponents[i]) {
-                for (; p != end; ++p)
-                    p->z = p->y = 0.f;
-            }
-            else if (3 == mesh->mNumUVComponents[i]) {
-                // Really 3D coordinates? Check whether the third coordinate is != 0 for at least one element
-                for (; p != end; ++p) {
-                    if (p->z != 0)
-                        break;
-                }
-                if (p == end) {
-                    ASSIMP_LOG_WARN("ScenePreprocessor: UVs are declared to be 3D but they're obviously not. Reverting to 2D.");
-                    mesh->mNumUVComponents[i] = 2;
-                }
-            }
-        }
-    }
-
-    // If the information which primitive types are there in the
-    // mesh is currently not available, compute it.
-    if (!mesh->mPrimitiveTypes) {
-        for (unsigned int a = 0; a < mesh->mNumFaces; ++a)  {
-            aiFace& face = mesh->mFaces[a];
-            switch (face.mNumIndices)
-            {
-            case 3u:
-                mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
-                break;
-
-            case 2u:
-                mesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
-                break;
-
-            case 1u:
-                mesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
-                break;
-
-            default:
-                mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
-                break;
-            }
-        }
-    }
-
-    // If tangents and normals are given but no bitangents compute them
-    if (mesh->mTangents && mesh->mNormals && !mesh->mBitangents)    {
-
-        mesh->mBitangents = new aiVector3D[mesh->mNumVertices];
-        for (unsigned int i = 0; i < mesh->mNumVertices;++i)    {
-            mesh->mBitangents[i] = mesh->mNormals[i] ^ mesh->mTangents[i];
-        }
-    }
-}
-
-// ---------------------------------------------------------------------------------------------
-void ScenePreprocessor::ProcessAnimation (aiAnimation* anim)
-{
-    double first = 10e10, last = -10e10;
-    for (unsigned int i = 0; i < anim->mNumChannels;++i)    {
-        aiNodeAnim* channel = anim->mChannels[i];
-
-        /*  If the exact duration of the animation is not given
-         *  compute it now.
-         */
-        if (anim->mDuration == -1.) {
-
-            // Position keys
-            for (unsigned int j = 0; j < channel->mNumPositionKeys;++j) {
-                aiVectorKey& key = channel->mPositionKeys[j];
-                first = std::min (first, key.mTime);
-                last  = std::max (last,  key.mTime);
-            }
-
-            // Scaling keys
-            for (unsigned int j = 0; j < channel->mNumScalingKeys;++j )  {
-                aiVectorKey& key = channel->mScalingKeys[j];
-                first = std::min (first, key.mTime);
-                last  = std::max (last,  key.mTime);
-            }
-
-            // Rotation keys
-            for (unsigned int j = 0; j < channel->mNumRotationKeys;++j ) {
-                aiQuatKey& key = channel->mRotationKeys[ j ];
-                first = std::min (first, key.mTime);
-                last  = std::max (last,  key.mTime);
-            }
-        }
-
-        /*  Check whether the animation channel has no rotation
-         *  or position tracks. In this case we generate a dummy
-         *  track from the information we have in the transformation
-         *  matrix of the corresponding node.
-         */
-        if (!channel->mNumRotationKeys || !channel->mNumPositionKeys || !channel->mNumScalingKeys)  {
-            // Find the node that belongs to this animation
-            aiNode* node = scene->mRootNode->FindNode(channel->mNodeName);
-            if (node) // ValidateDS will complain later if 'node' is NULL
-            {
-                // Decompose the transformation matrix of the node
-                aiVector3D scaling, position;
-                aiQuaternion rotation;
-
-                node->mTransformation.Decompose(scaling, rotation,position);
-
-                // No rotation keys? Generate a dummy track
-                if (!channel->mNumRotationKeys) {
-                    channel->mNumRotationKeys = 1;
-                    channel->mRotationKeys = new aiQuatKey[1];
-                    aiQuatKey& q = channel->mRotationKeys[0];
-
-                    q.mTime  = 0.;
-                    q.mValue = rotation;
-
-                    ASSIMP_LOG_DEBUG("ScenePreprocessor: Dummy rotation track has been generated");
-                }
-
-                // No scaling keys? Generate a dummy track
-                if (!channel->mNumScalingKeys)  {
-                    channel->mNumScalingKeys = 1;
-                    channel->mScalingKeys = new aiVectorKey[1];
-                    aiVectorKey& q = channel->mScalingKeys[0];
-
-                    q.mTime  = 0.;
-                    q.mValue = scaling;
-
-                    ASSIMP_LOG_DEBUG("ScenePreprocessor: Dummy scaling track has been generated");
-                }
-
-                // No position keys? Generate a dummy track
-                if (!channel->mNumPositionKeys) {
-                    channel->mNumPositionKeys = 1;
-                    channel->mPositionKeys = new aiVectorKey[1];
-                    aiVectorKey& q = channel->mPositionKeys[0];
-
-                    q.mTime  = 0.;
-                    q.mValue = position;
-
-                    ASSIMP_LOG_DEBUG("ScenePreprocessor: Dummy position track has been generated");
-                }
-            }
-        }
-    }
-
-    if (anim->mDuration == -1.)     {
-        ASSIMP_LOG_DEBUG("ScenePreprocessor: Setting animation duration");
-        anim->mDuration = last - std::min( first, 0. );
-    }
-}

+ 0 - 125
thirdparty/assimp/code/Common/ScenePreprocessor.h

@@ -1,125 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file Defines a post processing step to search all meshes for
-  degenerated faces */
-#ifndef AI_SCENE_PREPROCESSOR_H_INC
-#define AI_SCENE_PREPROCESSOR_H_INC
-
-#include <assimp/defs.h>
-#include <stddef.h>
-
-struct aiScene;
-struct aiAnimation;
-struct aiMesh;
-
-class ScenePreprocessorTest;
-namespace Assimp    {
-
-// ----------------------------------------------------------------------------------
-/** ScenePreprocessor: Preprocess a scene before any post-processing
- *  steps are executed.
- *
- *  The step computes data that needn't necessarily be provided by the
- *  importer, such as aiMesh::mPrimitiveTypes.
-*/
-// ----------------------------------------------------------------------------------
-class ASSIMP_API ScenePreprocessor
-{
-    // Make ourselves a friend of the corresponding test unit.
-    friend class ::ScenePreprocessorTest;
-public:
-
-    // ----------------------------------------------------------------
-    /** Default c'tpr. Use SetScene() to assign a scene to the object.
-     */
-    ScenePreprocessor()
-        :   scene   (NULL)
-    {}
-
-    /** Constructs the object and assigns a specific scene to it
-     */
-    ScenePreprocessor(aiScene* _scene)
-        :   scene   (_scene)
-    {}
-
-    // ----------------------------------------------------------------
-    /** Assign a (new) scene to the object.
-     *
-     *  One 'SceneProcessor' can be used for multiple scenes.
-     *  Call ProcessScene to have the scene preprocessed.
-     *  @param sc Scene to be processed.
-     */
-    void SetScene (aiScene* sc) {
-        scene = sc;
-    }
-
-    // ----------------------------------------------------------------
-    /** Preprocess the current scene
-     */
-    void ProcessScene ();
-
-protected:
-
-    // ----------------------------------------------------------------
-    /** Preprocess an animation in the scene
-     *  @param anim Anim to be preprocessed.
-     */
-    void ProcessAnimation (aiAnimation* anim);
-
-
-    // ----------------------------------------------------------------
-    /** Preprocess a mesh in the scene
-     *  @param mesh Mesh to be preprocessed.
-     */
-    void ProcessMesh (aiMesh* mesh);
-
-protected:
-
-    //! Scene we're currently working on
-    aiScene* scene;
-};
-
-
-} // ! end namespace Assimp
-
-#endif // include guard

+ 0 - 105
thirdparty/assimp/code/Common/ScenePrivate.h

@@ -1,105 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file Stuff to deal with aiScene::mPrivate
- */
-#pragma once
-#ifndef AI_SCENEPRIVATE_H_INCLUDED
-#define AI_SCENEPRIVATE_H_INCLUDED
-
-#include <assimp/ai_assert.h>
-#include <assimp/scene.h>
-
-namespace Assimp {
-
-// Forward declarations
-class Importer;
-
-struct ScenePrivateData {
-    //  The struct constructor.
-    ScenePrivateData() AI_NO_EXCEPT;
-
-    // Importer that originally loaded the scene though the C-API
-    // If set, this object is owned by this private data instance.
-    Assimp::Importer* mOrigImporter;
-
-    // List of post-processing steps already applied to the scene.
-    unsigned int mPPStepsApplied;
-
-    // true if the scene is a copy made with aiCopyScene()
-    // or the corresponding C++ API. This means that user code
-    // may have made modifications to it, so mPPStepsApplied
-    // and mOrigImporter are no longer safe to rely on and only
-    // serve informative purposes.
-    bool mIsCopy;
-};
-
-inline
-ScenePrivateData::ScenePrivateData() AI_NO_EXCEPT
-: mOrigImporter( nullptr )
-, mPPStepsApplied( 0 )
-, mIsCopy( false ) {
-    // empty
-}
-
-// Access private data stored in the scene
-inline
-ScenePrivateData* ScenePriv(aiScene* in) {
-    ai_assert( nullptr != in );
-    if ( nullptr == in ) {
-        return nullptr;
-    }
-    return static_cast<ScenePrivateData*>(in->mPrivate);
-}
-
-inline
-const ScenePrivateData* ScenePriv(const aiScene* in) {
-    ai_assert( nullptr != in );
-    if ( nullptr == in ) {
-        return nullptr;
-    }
-    return static_cast<const ScenePrivateData*>(in->mPrivate);
-}
-
-} // Namespace Assimp
-
-#endif // AI_SCENEPRIVATE_H_INCLUDED

+ 0 - 270
thirdparty/assimp/code/Common/SkeletonMeshBuilder.cpp

@@ -1,270 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-copyright notice, this list of conditions and the
-following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the
-following disclaimer in the documentation and/or other
-materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-contributors may be used to endorse or promote products
-derived from this software without specific prior
-written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file  SkeletonMeshBuilder.cpp
- *  @brief Implementation of a little class to construct a dummy mesh for a skeleton
- */
-
-#include <assimp/scene.h>
-#include <assimp/SkeletonMeshBuilder.h>
-
-using namespace Assimp;
-
-// ------------------------------------------------------------------------------------------------
-// The constructor processes the given scene and adds a mesh there.
-SkeletonMeshBuilder::SkeletonMeshBuilder( aiScene* pScene, aiNode* root, bool bKnobsOnly)
-{
-    // nothing to do if there's mesh data already present at the scene
-    if( pScene->mNumMeshes > 0 || pScene->mRootNode == NULL)
-        return;
-
-    if (!root)
-        root = pScene->mRootNode;
-
-    mKnobsOnly = bKnobsOnly;
-
-    // build some faces around each node
-    CreateGeometry( root );
-
-    // create a mesh to hold all the generated faces
-    pScene->mNumMeshes = 1;
-    pScene->mMeshes = new aiMesh*[1];
-    pScene->mMeshes[0] = CreateMesh();
-    // and install it at the root node
-    root->mNumMeshes = 1;
-    root->mMeshes = new unsigned int[1];
-    root->mMeshes[0] = 0;
-
-    // create a dummy material for the mesh
-    if(pScene->mNumMaterials==0){
-		pScene->mNumMaterials = 1;
-		pScene->mMaterials = new aiMaterial*[1];
-		pScene->mMaterials[0] = CreateMaterial();
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-// Recursively builds a simple mesh representation for the given node
-void SkeletonMeshBuilder::CreateGeometry( const aiNode* pNode)
-{
-    // add a joint entry for the node.
-    const unsigned int vertexStartIndex = static_cast<unsigned int>(mVertices.size());
-
-    // now build the geometry.
-    if( pNode->mNumChildren > 0 && !mKnobsOnly)
-    {
-        // If the node has children, we build little pointers to each of them
-        for( unsigned int a = 0; a < pNode->mNumChildren; a++)
-        {
-            // find a suitable coordinate system
-            const aiMatrix4x4& childTransform = pNode->mChildren[a]->mTransformation;
-            aiVector3D childpos( childTransform.a4, childTransform.b4, childTransform.c4);
-            ai_real distanceToChild = childpos.Length();
-            if( distanceToChild < 0.0001)
-                continue;
-            aiVector3D up = aiVector3D( childpos).Normalize();
-
-            aiVector3D orth( 1.0, 0.0, 0.0);
-            if( std::fabs( orth * up) > 0.99)
-                orth.Set( 0.0, 1.0, 0.0);
-
-            aiVector3D front = (up ^ orth).Normalize();
-            aiVector3D side = (front ^ up).Normalize();
-
-            unsigned int localVertexStart = static_cast<unsigned int>(mVertices.size());
-            mVertices.push_back( -front * distanceToChild * (ai_real)0.1);
-            mVertices.push_back( childpos);
-            mVertices.push_back( -side * distanceToChild * (ai_real)0.1);
-            mVertices.push_back( -side * distanceToChild * (ai_real)0.1);
-            mVertices.push_back( childpos);
-            mVertices.push_back( front * distanceToChild * (ai_real)0.1);
-            mVertices.push_back( front * distanceToChild * (ai_real)0.1);
-            mVertices.push_back( childpos);
-            mVertices.push_back( side * distanceToChild * (ai_real)0.1);
-            mVertices.push_back( side * distanceToChild * (ai_real)0.1);
-            mVertices.push_back( childpos);
-            mVertices.push_back( -front * distanceToChild * (ai_real)0.1);
-
-            mFaces.push_back( Face( localVertexStart + 0, localVertexStart + 1, localVertexStart + 2));
-            mFaces.push_back( Face( localVertexStart + 3, localVertexStart + 4, localVertexStart + 5));
-            mFaces.push_back( Face( localVertexStart + 6, localVertexStart + 7, localVertexStart + 8));
-            mFaces.push_back( Face( localVertexStart + 9, localVertexStart + 10, localVertexStart + 11));
-        }
-    }
-    else
-    {
-        // if the node has no children, it's an end node. Put a little knob there instead
-        aiVector3D ownpos( pNode->mTransformation.a4, pNode->mTransformation.b4, pNode->mTransformation.c4);
-        ai_real sizeEstimate = ownpos.Length() * ai_real( 0.18 );
-
-        mVertices.push_back( aiVector3D( -sizeEstimate, 0.0, 0.0));
-        mVertices.push_back( aiVector3D( 0.0, sizeEstimate, 0.0));
-        mVertices.push_back( aiVector3D( 0.0, 0.0, -sizeEstimate));
-        mVertices.push_back( aiVector3D( 0.0, sizeEstimate, 0.0));
-        mVertices.push_back( aiVector3D( sizeEstimate, 0.0, 0.0));
-        mVertices.push_back( aiVector3D( 0.0, 0.0, -sizeEstimate));
-        mVertices.push_back( aiVector3D( sizeEstimate, 0.0, 0.0));
-        mVertices.push_back( aiVector3D( 0.0, -sizeEstimate, 0.0));
-        mVertices.push_back( aiVector3D( 0.0, 0.0, -sizeEstimate));
-        mVertices.push_back( aiVector3D( 0.0, -sizeEstimate, 0.0));
-        mVertices.push_back( aiVector3D( -sizeEstimate, 0.0, 0.0));
-        mVertices.push_back( aiVector3D( 0.0, 0.0, -sizeEstimate));
-
-        mVertices.push_back( aiVector3D( -sizeEstimate, 0.0, 0.0));
-        mVertices.push_back( aiVector3D( 0.0, 0.0, sizeEstimate));
-        mVertices.push_back( aiVector3D( 0.0, sizeEstimate, 0.0));
-        mVertices.push_back( aiVector3D( 0.0, sizeEstimate, 0.0));
-        mVertices.push_back( aiVector3D( 0.0, 0.0, sizeEstimate));
-        mVertices.push_back( aiVector3D( sizeEstimate, 0.0, 0.0));
-        mVertices.push_back( aiVector3D( sizeEstimate, 0.0, 0.0));
-        mVertices.push_back( aiVector3D( 0.0, 0.0, sizeEstimate));
-        mVertices.push_back( aiVector3D( 0.0, -sizeEstimate, 0.0));
-        mVertices.push_back( aiVector3D( 0.0, -sizeEstimate, 0.0));
-        mVertices.push_back( aiVector3D( 0.0, 0.0, sizeEstimate));
-        mVertices.push_back( aiVector3D( -sizeEstimate, 0.0, 0.0));
-
-        mFaces.push_back( Face( vertexStartIndex + 0, vertexStartIndex + 1, vertexStartIndex + 2));
-        mFaces.push_back( Face( vertexStartIndex + 3, vertexStartIndex + 4, vertexStartIndex + 5));
-        mFaces.push_back( Face( vertexStartIndex + 6, vertexStartIndex + 7, vertexStartIndex + 8));
-        mFaces.push_back( Face( vertexStartIndex + 9, vertexStartIndex + 10, vertexStartIndex + 11));
-        mFaces.push_back( Face( vertexStartIndex + 12, vertexStartIndex + 13, vertexStartIndex + 14));
-        mFaces.push_back( Face( vertexStartIndex + 15, vertexStartIndex + 16, vertexStartIndex + 17));
-        mFaces.push_back( Face( vertexStartIndex + 18, vertexStartIndex + 19, vertexStartIndex + 20));
-        mFaces.push_back( Face( vertexStartIndex + 21, vertexStartIndex + 22, vertexStartIndex + 23));
-    }
-
-    unsigned int numVertices = static_cast<unsigned int>(mVertices.size() - vertexStartIndex);
-    if( numVertices > 0)
-    {
-        // create a bone affecting all the newly created vertices
-        aiBone* bone = new aiBone;
-        mBones.push_back( bone);
-        bone->mName = pNode->mName;
-
-        // calculate the bone offset matrix by concatenating the inverse transformations of all parents
-        bone->mOffsetMatrix = aiMatrix4x4( pNode->mTransformation).Inverse();
-        for( aiNode* parent = pNode->mParent; parent != NULL; parent = parent->mParent)
-            bone->mOffsetMatrix = aiMatrix4x4( parent->mTransformation).Inverse() * bone->mOffsetMatrix;
-
-        // add all the vertices to the bone's influences
-        bone->mNumWeights = numVertices;
-        bone->mWeights = new aiVertexWeight[numVertices];
-        for( unsigned int a = 0; a < numVertices; a++)
-            bone->mWeights[a] = aiVertexWeight( vertexStartIndex + a, 1.0);
-
-        // HACK: (thom) transform all vertices to the bone's local space. Should be done before adding
-        // them to the array, but I'm tired now and I'm annoyed.
-        aiMatrix4x4 boneToMeshTransform = aiMatrix4x4( bone->mOffsetMatrix).Inverse();
-        for( unsigned int a = vertexStartIndex; a < mVertices.size(); a++)
-            mVertices[a] = boneToMeshTransform * mVertices[a];
-    }
-
-    // and finally recurse into the children list
-    for( unsigned int a = 0; a < pNode->mNumChildren; a++)
-        CreateGeometry( pNode->mChildren[a]);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Creates the mesh from the internally accumulated stuff and returns it.
-aiMesh* SkeletonMeshBuilder::CreateMesh()
-{
-    aiMesh* mesh = new aiMesh();
-
-    // add points
-    mesh->mNumVertices = static_cast<unsigned int>(mVertices.size());
-    mesh->mVertices = new aiVector3D[mesh->mNumVertices];
-    std::copy( mVertices.begin(), mVertices.end(), mesh->mVertices);
-
-    mesh->mNormals = new aiVector3D[mesh->mNumVertices];
-
-    // add faces
-    mesh->mNumFaces = static_cast<unsigned int>(mFaces.size());
-    mesh->mFaces = new aiFace[mesh->mNumFaces];
-    for( unsigned int a = 0; a < mesh->mNumFaces; a++)
-    {
-        const Face& inface = mFaces[a];
-        aiFace& outface = mesh->mFaces[a];
-        outface.mNumIndices = 3;
-        outface.mIndices = new unsigned int[3];
-        outface.mIndices[0] = inface.mIndices[0];
-        outface.mIndices[1] = inface.mIndices[1];
-        outface.mIndices[2] = inface.mIndices[2];
-
-        // Compute per-face normals ... we don't want the bones to be smoothed ... they're built to visualize
-        // the skeleton, so it's good if there's a visual difference to the rest of the geometry
-        aiVector3D nor = ((mVertices[inface.mIndices[2]] - mVertices[inface.mIndices[0]]) ^
-            (mVertices[inface.mIndices[1]] - mVertices[inface.mIndices[0]]));
-
-        if (nor.Length() < 1e-5) /* ensure that FindInvalidData won't remove us ...*/
-            nor = aiVector3D(1.0,0.0,0.0);
-
-        for (unsigned int n = 0; n < 3; ++n)
-            mesh->mNormals[inface.mIndices[n]] = nor;
-    }
-
-    // add the bones
-    mesh->mNumBones = static_cast<unsigned int>(mBones.size());
-    mesh->mBones = new aiBone*[mesh->mNumBones];
-    std::copy( mBones.begin(), mBones.end(), mesh->mBones);
-
-    // default
-    mesh->mMaterialIndex = 0;
-
-    return mesh;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Creates a dummy material and returns it.
-aiMaterial* SkeletonMeshBuilder::CreateMaterial()
-{
-    aiMaterial* matHelper = new aiMaterial;
-
-    // Name
-    aiString matName( std::string( "SkeletonMaterial"));
-    matHelper->AddProperty( &matName, AI_MATKEY_NAME);
-
-    // Prevent backface culling
-    const int no_cull = 1;
-    matHelper->AddProperty(&no_cull,1,AI_MATKEY_TWOSIDED);
-
-    return matHelper;
-}

+ 0 - 342
thirdparty/assimp/code/Common/SpatialSort.cpp

@@ -1,342 +0,0 @@
-/*
----------------------------------------------------------------------------
-Open Asset Import Library (assimp)
----------------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the following
-conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------------
-*/
-
-/** @file Implementation of the helper class to quickly find vertices close to a given position */
-
-#include <assimp/SpatialSort.h>
-#include <assimp/ai_assert.h>
-
-using namespace Assimp;
-
-// CHAR_BIT seems to be defined under MVSC, but not under GCC. Pray that the correct value is 8.
-#ifndef CHAR_BIT
-#   define CHAR_BIT 8
-#endif
-
-// ------------------------------------------------------------------------------------------------
-// Constructs a spatially sorted representation from the given position array.
-SpatialSort::SpatialSort( const aiVector3D* pPositions, unsigned int pNumPositions,
-    unsigned int pElementOffset)
-
-    // define the reference plane. We choose some arbitrary vector away from all basic axises
-    // in the hope that no model spreads all its vertices along this plane.
-    : mPlaneNormal(0.8523f, 0.34321f, 0.5736f)
-{
-    mPlaneNormal.Normalize();
-    Fill(pPositions,pNumPositions,pElementOffset);
-}
-
-// ------------------------------------------------------------------------------------------------
-SpatialSort :: SpatialSort()
-: mPlaneNormal(0.8523f, 0.34321f, 0.5736f)
-{
-    mPlaneNormal.Normalize();
-}
-
-// ------------------------------------------------------------------------------------------------
-// Destructor
-SpatialSort::~SpatialSort()
-{
-    // nothing to do here, everything destructs automatically
-}
-
-// ------------------------------------------------------------------------------------------------
-void SpatialSort::Fill( const aiVector3D* pPositions, unsigned int pNumPositions,
-    unsigned int pElementOffset,
-    bool pFinalize /*= true */)
-{
-    mPositions.clear();
-    Append(pPositions,pNumPositions,pElementOffset,pFinalize);
-}
-
-// ------------------------------------------------------------------------------------------------
-void SpatialSort :: Finalize()
-{
-    std::sort( mPositions.begin(), mPositions.end());
-}
-
-// ------------------------------------------------------------------------------------------------
-void SpatialSort::Append( const aiVector3D* pPositions, unsigned int pNumPositions,
-    unsigned int pElementOffset,
-    bool pFinalize /*= true */)
-{
-    // store references to all given positions along with their distance to the reference plane
-    const size_t initial = mPositions.size();
-    mPositions.reserve(initial + (pFinalize?pNumPositions:pNumPositions*2));
-    for( unsigned int a = 0; a < pNumPositions; a++)
-    {
-        const char* tempPointer = reinterpret_cast<const char*> (pPositions);
-        const aiVector3D* vec   = reinterpret_cast<const aiVector3D*> (tempPointer + a * pElementOffset);
-
-        // store position by index and distance
-        ai_real distance = *vec * mPlaneNormal;
-        mPositions.push_back( Entry( static_cast<unsigned int>(a+initial), *vec, distance));
-    }
-
-    if (pFinalize) {
-        // now sort the array ascending by distance.
-        Finalize();
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-// Returns an iterator for all positions close to the given position.
-void SpatialSort::FindPositions( const aiVector3D& pPosition,
-    ai_real pRadius, std::vector<unsigned int>& poResults) const
-{
-    const ai_real dist = pPosition * mPlaneNormal;
-    const ai_real minDist = dist - pRadius, maxDist = dist + pRadius;
-
-    // clear the array
-    poResults.clear();
-
-    // quick check for positions outside the range
-    if( mPositions.size() == 0)
-        return;
-    if( maxDist < mPositions.front().mDistance)
-        return;
-    if( minDist > mPositions.back().mDistance)
-        return;
-
-    // do a binary search for the minimal distance to start the iteration there
-    unsigned int index = (unsigned int)mPositions.size() / 2;
-    unsigned int binaryStepSize = (unsigned int)mPositions.size() / 4;
-    while( binaryStepSize > 1)
-    {
-        if( mPositions[index].mDistance < minDist)
-            index += binaryStepSize;
-        else
-            index -= binaryStepSize;
-
-        binaryStepSize /= 2;
-    }
-
-    // depending on the direction of the last step we need to single step a bit back or forth
-    // to find the actual beginning element of the range
-    while( index > 0 && mPositions[index].mDistance > minDist)
-        index--;
-    while( index < (mPositions.size() - 1) && mPositions[index].mDistance < minDist)
-        index++;
-
-    // Mow start iterating from there until the first position lays outside of the distance range.
-    // Add all positions inside the distance range within the given radius to the result aray
-    std::vector<Entry>::const_iterator it = mPositions.begin() + index;
-    const ai_real pSquared = pRadius*pRadius;
-    while( it->mDistance < maxDist)
-    {
-        if( (it->mPosition - pPosition).SquareLength() < pSquared)
-            poResults.push_back( it->mIndex);
-        ++it;
-        if( it == mPositions.end())
-            break;
-    }
-
-    // that's it
-}
-
-namespace {
-
-    // Binary, signed-integer representation of a single-precision floating-point value.
-    // IEEE 754 says: "If two floating-point numbers in the same format are ordered then they are
-    //  ordered the same way when their bits are reinterpreted as sign-magnitude integers."
-    // This allows us to convert all floating-point numbers to signed integers of arbitrary size
-    //  and then use them to work with ULPs (Units in the Last Place, for high-precision
-    //  computations) or to compare them (integer comparisons are faster than floating-point
-    //  comparisons on many platforms).
-    typedef ai_int BinFloat;
-
-    // --------------------------------------------------------------------------------------------
-    // Converts the bit pattern of a floating-point number to its signed integer representation.
-    BinFloat ToBinary( const ai_real & pValue) {
-
-        // If this assertion fails, signed int is not big enough to store a float on your platform.
-        //  Please correct the declaration of BinFloat a few lines above - but do it in a portable,
-        //  #ifdef'd manner!
-        static_assert( sizeof(BinFloat) >= sizeof(ai_real), "sizeof(BinFloat) >= sizeof(ai_real)");
-
-        #if defined( _MSC_VER)
-            // If this assertion fails, Visual C++ has finally moved to ILP64. This means that this
-            //  code has just become legacy code! Find out the current value of _MSC_VER and modify
-            //  the #if above so it evaluates false on the current and all upcoming VC versions (or
-            //  on the current platform, if LP64 or LLP64 are still used on other platforms).
-            static_assert( sizeof(BinFloat) == sizeof(ai_real), "sizeof(BinFloat) == sizeof(ai_real)");
-
-            // This works best on Visual C++, but other compilers have their problems with it.
-            const BinFloat binValue = reinterpret_cast<BinFloat const &>(pValue);
-        #else
-            // On many compilers, reinterpreting a float address as an integer causes aliasing
-            // problems. This is an ugly but more or less safe way of doing it.
-            union {
-                ai_real     asFloat;
-                BinFloat    asBin;
-            } conversion;
-            conversion.asBin    = 0; // zero empty space in case sizeof(BinFloat) > sizeof(float)
-            conversion.asFloat  = pValue;
-            const BinFloat binValue = conversion.asBin;
-        #endif
-
-        // floating-point numbers are of sign-magnitude format, so find out what signed number
-        //  representation we must convert negative values to.
-        // See http://en.wikipedia.org/wiki/Signed_number_representations.
-
-        // Two's complement?
-        if( (-42 == (~42 + 1)) && (binValue & 0x80000000))
-            return BinFloat(1 << (CHAR_BIT * sizeof(BinFloat) - 1)) - binValue;
-        // One's complement?
-        else if ( (-42 == ~42) && (binValue & 0x80000000))
-            return BinFloat(-0) - binValue;
-        // Sign-magnitude?
-        else if( (-42 == (42 | (-0))) && (binValue & 0x80000000)) // -0 = 1000... binary
-            return binValue;
-        else
-            return binValue;
-    }
-
-} // namespace
-
-// ------------------------------------------------------------------------------------------------
-// Fills an array with indices of all positions identical to the given position. In opposite to
-// FindPositions(), not an epsilon is used but a (very low) tolerance of four floating-point units.
-void SpatialSort::FindIdenticalPositions( const aiVector3D& pPosition,
-    std::vector<unsigned int>& poResults) const
-{
-    // Epsilons have a huge disadvantage: they are of constant precision, while floating-point
-    //  values are of log2 precision. If you apply e=0.01 to 100, the epsilon is rather small, but
-    //  if you apply it to 0.001, it is enormous.
-
-    // The best way to overcome this is the unit in the last place (ULP). A precision of 2 ULPs
-    //  tells us that a float does not differ more than 2 bits from the "real" value. ULPs are of
-    //  logarithmic precision - around 1, they are 1*(2^24) and around 10000, they are 0.00125.
-
-    // For standard C math, we can assume a precision of 0.5 ULPs according to IEEE 754. The
-    //  incoming vertex positions might have already been transformed, probably using rather
-    //  inaccurate SSE instructions, so we assume a tolerance of 4 ULPs to safely identify
-    //  identical vertex positions.
-    static const int toleranceInULPs = 4;
-    // An interesting point is that the inaccuracy grows linear with the number of operations:
-    //  multiplying to numbers, each inaccurate to four ULPs, results in an inaccuracy of four ULPs
-    //  plus 0.5 ULPs for the multiplication.
-    // To compute the distance to the plane, a dot product is needed - that is a multiplication and
-    //  an addition on each number.
-    static const int distanceToleranceInULPs = toleranceInULPs + 1;
-    // The squared distance between two 3D vectors is computed the same way, but with an additional
-    //  subtraction.
-    static const int distance3DToleranceInULPs = distanceToleranceInULPs + 1;
-
-    // Convert the plane distance to its signed integer representation so the ULPs tolerance can be
-    //  applied. For some reason, VC won't optimize two calls of the bit pattern conversion.
-    const BinFloat minDistBinary = ToBinary( pPosition * mPlaneNormal) - distanceToleranceInULPs;
-    const BinFloat maxDistBinary = minDistBinary + 2 * distanceToleranceInULPs;
-
-    // clear the array in this strange fashion because a simple clear() would also deallocate
-    // the array which we want to avoid
-    poResults.resize( 0 );
-
-    // do a binary search for the minimal distance to start the iteration there
-    unsigned int index = (unsigned int)mPositions.size() / 2;
-    unsigned int binaryStepSize = (unsigned int)mPositions.size() / 4;
-    while( binaryStepSize > 1)
-    {
-        // Ugly, but conditional jumps are faster with integers than with floats
-        if( minDistBinary > ToBinary(mPositions[index].mDistance))
-            index += binaryStepSize;
-        else
-            index -= binaryStepSize;
-
-        binaryStepSize /= 2;
-    }
-
-    // depending on the direction of the last step we need to single step a bit back or forth
-    // to find the actual beginning element of the range
-    while( index > 0 && minDistBinary < ToBinary(mPositions[index].mDistance) )
-        index--;
-    while( index < (mPositions.size() - 1) && minDistBinary > ToBinary(mPositions[index].mDistance))
-        index++;
-
-    // Now start iterating from there until the first position lays outside of the distance range.
-    // Add all positions inside the distance range within the tolerance to the result array
-    std::vector<Entry>::const_iterator it = mPositions.begin() + index;
-    while( ToBinary(it->mDistance) < maxDistBinary)
-    {
-        if( distance3DToleranceInULPs >= ToBinary((it->mPosition - pPosition).SquareLength()))
-            poResults.push_back(it->mIndex);
-        ++it;
-        if( it == mPositions.end())
-            break;
-    }
-
-    // that's it
-}
-
-// ------------------------------------------------------------------------------------------------
-unsigned int SpatialSort::GenerateMappingTable(std::vector<unsigned int>& fill, ai_real pRadius) const
-{
-    fill.resize(mPositions.size(),UINT_MAX);
-    ai_real dist, maxDist;
-
-    unsigned int t=0;
-    const ai_real pSquared = pRadius*pRadius;
-    for (size_t i = 0; i < mPositions.size();) {
-        dist = mPositions[i].mPosition * mPlaneNormal;
-        maxDist = dist + pRadius;
-
-        fill[mPositions[i].mIndex] = t;
-        const aiVector3D& oldpos = mPositions[i].mPosition;
-        for (++i; i < fill.size() && mPositions[i].mDistance < maxDist
-            && (mPositions[i].mPosition - oldpos).SquareLength() < pSquared; ++i)
-        {
-            fill[mPositions[i].mIndex] = t;
-        }
-        ++t;
-    }
-
-#ifdef ASSIMP_BUILD_DEBUG
-
-    // debug invariant: mPositions[i].mIndex values must range from 0 to mPositions.size()-1
-    for (size_t i = 0; i < fill.size(); ++i) {
-        ai_assert(fill[i]<mPositions.size());
-    }
-
-#endif
-    return t;
-}

+ 0 - 407
thirdparty/assimp/code/Common/SplitByBoneCountProcess.cpp

@@ -1,407 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-
-/// @file SplitByBoneCountProcess.cpp
-/// Implementation of the SplitByBoneCount postprocessing step
-
-// internal headers of the post-processing framework
-#include "SplitByBoneCountProcess.h"
-#include <assimp/postprocess.h>
-#include <assimp/DefaultLogger.hpp>
-
-#include <limits>
-#include <assimp/TinyFormatter.h>
-
-using namespace Assimp;
-using namespace Assimp::Formatter;
-
-// ------------------------------------------------------------------------------------------------
-// Constructor
-SplitByBoneCountProcess::SplitByBoneCountProcess()
-{
-    // set default, might be overridden by importer config
-    mMaxBoneCount = AI_SBBC_DEFAULT_MAX_BONES;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Destructor
-SplitByBoneCountProcess::~SplitByBoneCountProcess()
-{
-    // nothing to do here
-}
-
-// ------------------------------------------------------------------------------------------------
-// Returns whether the processing step is present in the given flag.
-bool SplitByBoneCountProcess::IsActive( unsigned int pFlags) const
-{
-    return !!(pFlags & aiProcess_SplitByBoneCount);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Updates internal properties
-void SplitByBoneCountProcess::SetupProperties(const Importer* pImp)
-{
-    mMaxBoneCount = pImp->GetPropertyInteger(AI_CONFIG_PP_SBBC_MAX_BONES,AI_SBBC_DEFAULT_MAX_BONES);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Executes the post processing step on the given imported data.
-void SplitByBoneCountProcess::Execute( aiScene* pScene)
-{
-    ASSIMP_LOG_DEBUG("SplitByBoneCountProcess begin");
-
-    // early out
-    bool isNecessary = false;
-    for( unsigned int a = 0; a < pScene->mNumMeshes; ++a)
-        if( pScene->mMeshes[a]->mNumBones > mMaxBoneCount )
-            isNecessary = true;
-
-    if( !isNecessary )
-    {
-        ASSIMP_LOG_DEBUG( format() << "SplitByBoneCountProcess early-out: no meshes with more than " << mMaxBoneCount << " bones." );
-        return;
-    }
-
-    // we need to do something. Let's go.
-    mSubMeshIndices.clear();
-    mSubMeshIndices.resize( pScene->mNumMeshes);
-
-    // build a new array of meshes for the scene
-    std::vector<aiMesh*> meshes;
-
-    for( unsigned int a = 0; a < pScene->mNumMeshes; ++a)
-    {
-        aiMesh* srcMesh = pScene->mMeshes[a];
-
-        std::vector<aiMesh*> newMeshes;
-        SplitMesh( pScene->mMeshes[a], newMeshes);
-
-        // mesh was split
-        if( !newMeshes.empty() )
-        {
-            // store new meshes and indices of the new meshes
-            for( unsigned int b = 0; b < newMeshes.size(); ++b)
-            {
-                mSubMeshIndices[a].push_back( static_cast<unsigned int>(meshes.size()));
-                meshes.push_back( newMeshes[b]);
-            }
-
-            // and destroy the source mesh. It should be completely contained inside the new submeshes
-            delete srcMesh;
-        }
-        else
-        {
-            // Mesh is kept unchanged - store it's new place in the mesh array
-            mSubMeshIndices[a].push_back( static_cast<unsigned int>(meshes.size()));
-            meshes.push_back( srcMesh);
-        }
-    }
-
-    // rebuild the scene's mesh array
-    pScene->mNumMeshes = static_cast<unsigned int>(meshes.size());
-    delete [] pScene->mMeshes;
-    pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
-    std::copy( meshes.begin(), meshes.end(), pScene->mMeshes);
-
-    // recurse through all nodes and translate the node's mesh indices to fit the new mesh array
-    UpdateNode( pScene->mRootNode);
-
-    ASSIMP_LOG_DEBUG( format() << "SplitByBoneCountProcess end: split " << mSubMeshIndices.size() << " meshes into " << meshes.size() << " submeshes." );
-}
-
-// ------------------------------------------------------------------------------------------------
-// Splits the given mesh by bone count.
-void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh*>& poNewMeshes) const
-{
-    // skip if not necessary
-    if( pMesh->mNumBones <= mMaxBoneCount )
-        return;
-
-    // necessary optimisation: build a list of all affecting bones for each vertex
-    // TODO: (thom) maybe add a custom allocator here to avoid allocating tens of thousands of small arrays
-    typedef std::pair<unsigned int, float> BoneWeight;
-    std::vector< std::vector<BoneWeight> > vertexBones( pMesh->mNumVertices);
-    for( unsigned int a = 0; a < pMesh->mNumBones; ++a)
-    {
-        const aiBone* bone = pMesh->mBones[a];
-        for( unsigned int b = 0; b < bone->mNumWeights; ++b)
-            vertexBones[ bone->mWeights[b].mVertexId ].push_back( BoneWeight( a, bone->mWeights[b].mWeight));
-    }
-
-    unsigned int numFacesHandled = 0;
-    std::vector<bool> isFaceHandled( pMesh->mNumFaces, false);
-    while( numFacesHandled < pMesh->mNumFaces )
-    {
-        // which bones are used in the current submesh
-        unsigned int numBones = 0;
-        std::vector<bool> isBoneUsed( pMesh->mNumBones, false);
-        // indices of the faces which are going to go into this submesh
-        std::vector<unsigned int> subMeshFaces;
-        subMeshFaces.reserve( pMesh->mNumFaces);
-        // accumulated vertex count of all the faces in this submesh
-        unsigned int numSubMeshVertices = 0;
-        // a small local array of new bones for the current face. State of all used bones for that face
-        // can only be updated AFTER the face is completely analysed. Thanks to imre for the fix.
-        std::vector<unsigned int> newBonesAtCurrentFace;
-
-        // add faces to the new submesh as long as all bones affecting the faces' vertices fit in the limit
-        for( unsigned int a = 0; a < pMesh->mNumFaces; ++a)
-        {
-            // skip if the face is already stored in a submesh
-            if( isFaceHandled[a] )
-                continue;
-
-            const aiFace& face = pMesh->mFaces[a];
-            // check every vertex if its bones would still fit into the current submesh
-            for( unsigned int b = 0; b < face.mNumIndices; ++b )
-            {
-                const std::vector<BoneWeight>& vb = vertexBones[face.mIndices[b]];
-                for( unsigned int c = 0; c < vb.size(); ++c)
-                {
-                    unsigned int boneIndex = vb[c].first;
-                    // if the bone is already used in this submesh, it's ok
-                    if( isBoneUsed[boneIndex] )
-                        continue;
-
-                    // if it's not used, yet, we would need to add it. Store its bone index
-                    if( std::find( newBonesAtCurrentFace.begin(), newBonesAtCurrentFace.end(), boneIndex) == newBonesAtCurrentFace.end() )
-                        newBonesAtCurrentFace.push_back( boneIndex);
-                }
-            }
-
-            // leave out the face if the new bones required for this face don't fit the bone count limit anymore
-            if( numBones + newBonesAtCurrentFace.size() > mMaxBoneCount )
-                continue;
-
-            // mark all new bones as necessary
-            while( !newBonesAtCurrentFace.empty() )
-            {
-                unsigned int newIndex = newBonesAtCurrentFace.back();
-                newBonesAtCurrentFace.pop_back(); // this also avoids the deallocation which comes with a clear()
-                if( isBoneUsed[newIndex] )
-                    continue;
-
-                isBoneUsed[newIndex] = true;
-                numBones++;
-            }
-
-            // store the face index and the vertex count
-            subMeshFaces.push_back( a);
-            numSubMeshVertices += face.mNumIndices;
-
-            // remember that this face is handled
-            isFaceHandled[a] = true;
-            numFacesHandled++;
-        }
-
-        // create a new mesh to hold this subset of the source mesh
-        aiMesh* newMesh = new aiMesh;
-        if( pMesh->mName.length > 0 )
-            newMesh->mName.Set( format() << pMesh->mName.data << "_sub" << poNewMeshes.size());
-        newMesh->mMaterialIndex = pMesh->mMaterialIndex;
-        newMesh->mPrimitiveTypes = pMesh->mPrimitiveTypes;
-        poNewMeshes.push_back( newMesh);
-
-        // create all the arrays for this mesh if the old mesh contained them
-        newMesh->mNumVertices = numSubMeshVertices;
-        newMesh->mNumFaces = static_cast<unsigned int>(subMeshFaces.size());
-        newMesh->mVertices = new aiVector3D[newMesh->mNumVertices];
-        if( pMesh->HasNormals() )
-            newMesh->mNormals = new aiVector3D[newMesh->mNumVertices];
-        if( pMesh->HasTangentsAndBitangents() )
-        {
-            newMesh->mTangents = new aiVector3D[newMesh->mNumVertices];
-            newMesh->mBitangents = new aiVector3D[newMesh->mNumVertices];
-        }
-        for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a )
-        {
-            if( pMesh->HasTextureCoords( a) )
-                newMesh->mTextureCoords[a] = new aiVector3D[newMesh->mNumVertices];
-            newMesh->mNumUVComponents[a] = pMesh->mNumUVComponents[a];
-        }
-        for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a )
-        {
-            if( pMesh->HasVertexColors( a) )
-                newMesh->mColors[a] = new aiColor4D[newMesh->mNumVertices];
-        }
-
-        // and copy over the data, generating faces with linear indices along the way
-        newMesh->mFaces = new aiFace[subMeshFaces.size()];
-        unsigned int nvi = 0; // next vertex index
-        std::vector<unsigned int> previousVertexIndices( numSubMeshVertices, std::numeric_limits<unsigned int>::max()); // per new vertex: its index in the source mesh
-        for( unsigned int a = 0; a < subMeshFaces.size(); ++a )
-        {
-            const aiFace& srcFace = pMesh->mFaces[subMeshFaces[a]];
-            aiFace& dstFace = newMesh->mFaces[a];
-            dstFace.mNumIndices = srcFace.mNumIndices;
-            dstFace.mIndices = new unsigned int[dstFace.mNumIndices];
-
-            // accumulate linearly all the vertices of the source face
-            for( unsigned int b = 0; b < dstFace.mNumIndices; ++b )
-            {
-                unsigned int srcIndex = srcFace.mIndices[b];
-                dstFace.mIndices[b] = nvi;
-                previousVertexIndices[nvi] = srcIndex;
-
-                newMesh->mVertices[nvi] = pMesh->mVertices[srcIndex];
-                if( pMesh->HasNormals() )
-                    newMesh->mNormals[nvi] = pMesh->mNormals[srcIndex];
-                if( pMesh->HasTangentsAndBitangents() )
-                {
-                    newMesh->mTangents[nvi] = pMesh->mTangents[srcIndex];
-                    newMesh->mBitangents[nvi] = pMesh->mBitangents[srcIndex];
-                }
-                for( unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++c )
-                {
-                    if( pMesh->HasTextureCoords( c) )
-                        newMesh->mTextureCoords[c][nvi] = pMesh->mTextureCoords[c][srcIndex];
-                }
-                for( unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS; ++c )
-                {
-                    if( pMesh->HasVertexColors( c) )
-                        newMesh->mColors[c][nvi] = pMesh->mColors[c][srcIndex];
-                }
-
-                nvi++;
-            }
-        }
-
-        ai_assert( nvi == numSubMeshVertices );
-
-        // Create the bones for the new submesh: first create the bone array
-        newMesh->mNumBones = 0;
-        newMesh->mBones = new aiBone*[numBones];
-
-        std::vector<unsigned int> mappedBoneIndex( pMesh->mNumBones, std::numeric_limits<unsigned int>::max());
-        for( unsigned int a = 0; a < pMesh->mNumBones; ++a )
-        {
-            if( !isBoneUsed[a] )
-                continue;
-
-            // create the new bone
-            const aiBone* srcBone = pMesh->mBones[a];
-            aiBone* dstBone = new aiBone;
-            mappedBoneIndex[a] = newMesh->mNumBones;
-            newMesh->mBones[newMesh->mNumBones++] = dstBone;
-            dstBone->mName = srcBone->mName;
-            dstBone->mOffsetMatrix = srcBone->mOffsetMatrix;
-            dstBone->mNumWeights = 0;
-        }
-
-        ai_assert( newMesh->mNumBones == numBones );
-
-        // iterate over all new vertices and count which bones affected its old vertex in the source mesh
-        for( unsigned int a = 0; a < numSubMeshVertices; ++a )
-        {
-            unsigned int oldIndex = previousVertexIndices[a];
-            const std::vector<BoneWeight>& bonesOnThisVertex = vertexBones[oldIndex];
-
-            for( unsigned int b = 0; b < bonesOnThisVertex.size(); ++b )
-            {
-                unsigned int newBoneIndex = mappedBoneIndex[ bonesOnThisVertex[b].first ];
-                if( newBoneIndex != std::numeric_limits<unsigned int>::max() )
-                    newMesh->mBones[newBoneIndex]->mNumWeights++;
-            }
-        }
-
-        // allocate all bone weight arrays accordingly
-        for( unsigned int a = 0; a < newMesh->mNumBones; ++a )
-        {
-            aiBone* bone = newMesh->mBones[a];
-            ai_assert( bone->mNumWeights > 0 );
-            bone->mWeights = new aiVertexWeight[bone->mNumWeights];
-            bone->mNumWeights = 0; // for counting up in the next step
-        }
-
-        // now copy all the bone vertex weights for all the vertices which made it into the new submesh
-        for( unsigned int a = 0; a < numSubMeshVertices; ++a)
-        {
-            // find the source vertex for it in the source mesh
-            unsigned int previousIndex = previousVertexIndices[a];
-            // these bones were affecting it
-            const std::vector<BoneWeight>& bonesOnThisVertex = vertexBones[previousIndex];
-            // all of the bones affecting it should be present in the new submesh, or else
-            // the face it comprises shouldn't be present
-            for( unsigned int b = 0; b < bonesOnThisVertex.size(); ++b)
-            {
-                unsigned int newBoneIndex = mappedBoneIndex[ bonesOnThisVertex[b].first ];
-                ai_assert( newBoneIndex != std::numeric_limits<unsigned int>::max() );
-                aiVertexWeight* dstWeight = newMesh->mBones[newBoneIndex]->mWeights + newMesh->mBones[newBoneIndex]->mNumWeights;
-                newMesh->mBones[newBoneIndex]->mNumWeights++;
-
-                dstWeight->mVertexId = a;
-                dstWeight->mWeight = bonesOnThisVertex[b].second;
-            }
-        }
-
-        // I have the strange feeling that this will break apart at some point in time...
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-// Recursively updates the node's mesh list to account for the changed mesh list
-void SplitByBoneCountProcess::UpdateNode( aiNode* pNode) const
-{
-    // rebuild the node's mesh index list
-    if( pNode->mNumMeshes > 0 )
-    {
-        std::vector<unsigned int> newMeshList;
-        for( unsigned int a = 0; a < pNode->mNumMeshes; ++a)
-        {
-            unsigned int srcIndex = pNode->mMeshes[a];
-            const std::vector<unsigned int>& replaceMeshes = mSubMeshIndices[srcIndex];
-            newMeshList.insert( newMeshList.end(), replaceMeshes.begin(), replaceMeshes.end());
-        }
-
-        delete [] pNode->mMeshes;
-        pNode->mNumMeshes = static_cast<unsigned int>(newMeshList.size());
-        pNode->mMeshes = new unsigned int[pNode->mNumMeshes];
-        std::copy( newMeshList.begin(), newMeshList.end(), pNode->mMeshes);
-    }
-
-    // do that also recursively for all children
-    for( unsigned int a = 0; a < pNode->mNumChildren; ++a )
-    {
-        UpdateNode( pNode->mChildren[a]);
-    }
-}

+ 0 - 111
thirdparty/assimp/code/Common/SplitByBoneCountProcess.h

@@ -1,111 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/// @file SplitByBoneCountProcess.h
-/// Defines a post processing step to split meshes with many bones into submeshes
-#ifndef AI_SPLITBYBONECOUNTPROCESS_H_INC
-#define AI_SPLITBYBONECOUNTPROCESS_H_INC
-
-#include <vector>
-#include "BaseProcess.h"
-
-#include <assimp/mesh.h>
-#include <assimp/scene.h>
-
-namespace Assimp
-{
-
-
-/** Postprocessing filter to split meshes with many bones into submeshes
- * so that each submesh has a certain max bone count.
- *
- * Applied BEFORE the JoinVertices-Step occurs.
- * Returns NON-UNIQUE vertices, splits by bone count.
-*/
-class SplitByBoneCountProcess : public BaseProcess
-{
-public:
-
-    SplitByBoneCountProcess();
-    ~SplitByBoneCountProcess();
-
-public:
-    /** Returns whether the processing step is present in the given flag.
-    * @param pFlags The processing flags the importer was called with. A
-    *   bitwise combination of #aiPostProcessSteps.
-    * @return true if the process is present in this flag fields,
-    *   false if not.
-    */
-    bool IsActive( unsigned int pFlags) const;
-
-    /** Called prior to ExecuteOnScene().
-    * The function is a request to the process to update its configuration
-    * basing on the Importer's configuration property list.
-    */
-    virtual void SetupProperties(const Importer* pImp);
-
-protected:
-    /** Executes the post processing step on the given imported data.
-    * At the moment a process is not supposed to fail.
-    * @param pScene The imported data to work at.
-    */
-    void Execute( aiScene* pScene);
-
-    /// Splits the given mesh by bone count.
-    /// @param pMesh the Mesh to split. Is not changed at all, but might be superfluous in case it was split.
-    /// @param poNewMeshes Array of submeshes created in the process. Empty if splitting was not necessary.
-    void SplitMesh( const aiMesh* pMesh, std::vector<aiMesh*>& poNewMeshes) const;
-
-    /// Recursively updates the node's mesh list to account for the changed mesh list
-    void UpdateNode( aiNode* pNode) const;
-
-public:
-    /// Max bone count. Splitting occurs if a mesh has more than that number of bones.
-    size_t mMaxBoneCount;
-
-    /// Per mesh index: Array of indices of the new submeshes.
-    std::vector< std::vector<unsigned int> > mSubMeshIndices;
-};
-
-} // end of namespace Assimp
-
-#endif // !!AI_SPLITBYBONECOUNTPROCESS_H_INC

+ 0 - 507
thirdparty/assimp/code/Common/StandardShapes.cpp

@@ -1,507 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file   StandardShapes.cpp
- *  @brief  Implementation of the StandardShapes class
- *
- *  The primitive geometry data comes from
- *  http://geometrictools.com/Documentation/PlatonicSolids.pdf.
- */
-
-#include <assimp/StandardShapes.h>
-#include <assimp/StringComparison.h>
-#include <stddef.h>
-#include <assimp/Defines.h>
-#include <assimp/mesh.h>
-
-namespace Assimp    {
-
-
-# define ADD_TRIANGLE(n0,n1,n2) \
-    positions.push_back(n0); \
-    positions.push_back(n1); \
-    positions.push_back(n2);
-
-#   define ADD_PENTAGON(n0,n1,n2,n3,n4) \
-    if (polygons) \
-    { \
-        positions.push_back(n0); \
-        positions.push_back(n1); \
-        positions.push_back(n2); \
-        positions.push_back(n3); \
-        positions.push_back(n4); \
-    } \
-    else \
-    { \
-        ADD_TRIANGLE(n0, n1, n2) \
-        ADD_TRIANGLE(n0, n2, n3) \
-        ADD_TRIANGLE(n0, n3, n4) \
-    }
-
-#   define ADD_QUAD(n0,n1,n2,n3) \
-    if (polygons) \
-    { \
-        positions.push_back(n0); \
-        positions.push_back(n1); \
-        positions.push_back(n2); \
-        positions.push_back(n3); \
-    } \
-    else \
-    { \
-        ADD_TRIANGLE(n0, n1, n2) \
-        ADD_TRIANGLE(n0, n2, n3) \
-    }
-
-
-// ------------------------------------------------------------------------------------------------
-// Fast subdivision for a mesh whose verts have a magnitude of 1
-void Subdivide(std::vector<aiVector3D>& positions)
-{
-    // assume this to be constant - (fixme: must be 1.0? I think so)
-    const ai_real fl1 = positions[0].Length();
-
-    unsigned int origSize = (unsigned int)positions.size();
-    for (unsigned int i = 0 ; i < origSize ; i+=3)
-    {
-        aiVector3D& tv0 = positions[i];
-        aiVector3D& tv1 = positions[i+1];
-        aiVector3D& tv2 = positions[i+2];
-
-        aiVector3D a = tv0, b = tv1, c = tv2;
-        aiVector3D v1 = aiVector3D(a.x+b.x, a.y+b.y, a.z+b.z).Normalize()*fl1;
-        aiVector3D v2 = aiVector3D(a.x+c.x, a.y+c.y, a.z+c.z).Normalize()*fl1;
-        aiVector3D v3 = aiVector3D(b.x+c.x, b.y+c.y, b.z+c.z).Normalize()*fl1;
-
-        tv0 = v1; tv1 = v3; tv2 = v2; // overwrite the original
-        ADD_TRIANGLE(v1, v2, a);
-        ADD_TRIANGLE(v2, v3, c);
-        ADD_TRIANGLE(v3, v1, b);
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-// Construct a mesh from given vertex positions
-aiMesh* StandardShapes::MakeMesh(const std::vector<aiVector3D>& positions,
-    unsigned int numIndices)
-{
-    if (positions.empty() || !numIndices) return NULL;
-
-    // Determine which kinds of primitives the mesh consists of
-    aiMesh* out = new aiMesh();
-    switch (numIndices) {
-        case 1:
-            out->mPrimitiveTypes = aiPrimitiveType_POINT;
-            break;
-        case 2:
-            out->mPrimitiveTypes = aiPrimitiveType_LINE;
-            break;
-        case 3:
-            out->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
-            break;
-        default:
-            out->mPrimitiveTypes = aiPrimitiveType_POLYGON;
-            break;
-    };
-
-    out->mNumFaces = (unsigned int)positions.size() / numIndices;
-    out->mFaces = new aiFace[out->mNumFaces];
-    for (unsigned int i = 0, a = 0; i < out->mNumFaces;++i) {
-        aiFace& f = out->mFaces[i];
-        f.mNumIndices = numIndices;
-        f.mIndices = new unsigned int[numIndices];
-        for (unsigned int j = 0; i < numIndices; ++i, ++a) {
-            f.mIndices[j] = a;
-        }
-    }
-    out->mNumVertices = (unsigned int)positions.size();
-    out->mVertices = new aiVector3D[out->mNumVertices];
-    ::memcpy(out->mVertices,&positions[0],out->mNumVertices*sizeof(aiVector3D));
-
-    return out;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Construct a mesh with a specific shape (callback)
-aiMesh* StandardShapes::MakeMesh ( unsigned int (*GenerateFunc)(
-    std::vector<aiVector3D>&))
-{
-    std::vector<aiVector3D> temp;
-    unsigned num = (*GenerateFunc)(temp);
-    return MakeMesh(temp,num);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Construct a mesh with a specific shape (callback)
-aiMesh* StandardShapes::MakeMesh ( unsigned int (*GenerateFunc)(
-    std::vector<aiVector3D>&, bool))
-{
-    std::vector<aiVector3D> temp;
-    unsigned num = (*GenerateFunc)(temp,true);
-    return MakeMesh(temp,num);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Construct a mesh with a specific shape (callback)
-aiMesh* StandardShapes::MakeMesh (unsigned int num,  void (*GenerateFunc)(
-    unsigned int,std::vector<aiVector3D>&))
-{
-    std::vector<aiVector3D> temp;
-    (*GenerateFunc)(num,temp);
-    return MakeMesh(temp,3);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Build an incosahedron with points.magnitude == 1
-unsigned int StandardShapes::MakeIcosahedron(std::vector<aiVector3D>& positions)
-{
-    positions.reserve(positions.size()+60);
-
-    const ai_real t = ( ai_real( 1.0 )+ ai_real( 2.236067977 ) ) / ai_real( 2.0 );
-    const ai_real s = std::sqrt(ai_real(1.0) + t*t);
-
-    const aiVector3D v0  = aiVector3D(t,1.0, 0.0)/s;
-    const aiVector3D v1  = aiVector3D(-t,1.0, 0.0)/s;
-    const aiVector3D v2  = aiVector3D(t,-1.0, 0.0)/s;
-    const aiVector3D v3  = aiVector3D(-t,-1.0, 0.0)/s;
-    const aiVector3D v4  = aiVector3D(1.0, 0.0, t)/s;
-    const aiVector3D v5  = aiVector3D(1.0, 0.0,-t)/s;
-    const aiVector3D v6  = aiVector3D(-1.0, 0.0,t)/s;
-    const aiVector3D v7  = aiVector3D(-1.0, 0.0,-t)/s;
-    const aiVector3D v8  = aiVector3D(0.0, t, 1.0)/s;
-    const aiVector3D v9  = aiVector3D(0.0,-t, 1.0)/s;
-    const aiVector3D v10 = aiVector3D(0.0, t,-1.0)/s;
-    const aiVector3D v11 = aiVector3D(0.0,-t,-1.0)/s;
-
-    ADD_TRIANGLE(v0,v8,v4);
-    ADD_TRIANGLE(v0,v5,v10);
-    ADD_TRIANGLE(v2,v4,v9);
-    ADD_TRIANGLE(v2,v11,v5);
-
-    ADD_TRIANGLE(v1,v6,v8);
-    ADD_TRIANGLE(v1,v10,v7);
-    ADD_TRIANGLE(v3,v9,v6);
-    ADD_TRIANGLE(v3,v7,v11);
-
-    ADD_TRIANGLE(v0,v10,v8);
-    ADD_TRIANGLE(v1,v8,v10);
-    ADD_TRIANGLE(v2,v9,v11);
-    ADD_TRIANGLE(v3,v11,v9);
-
-    ADD_TRIANGLE(v4,v2,v0);
-    ADD_TRIANGLE(v5,v0,v2);
-    ADD_TRIANGLE(v6,v1,v3);
-    ADD_TRIANGLE(v7,v3,v1);
-
-    ADD_TRIANGLE(v8,v6,v4);
-    ADD_TRIANGLE(v9,v4,v6);
-    ADD_TRIANGLE(v10,v5,v7);
-    ADD_TRIANGLE(v11,v7,v5);
-    return 3;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Build a dodecahedron with points.magnitude == 1
-unsigned int StandardShapes::MakeDodecahedron(std::vector<aiVector3D>& positions,
-    bool polygons /*= false*/)
-{
-    positions.reserve(positions.size()+108);
-
-    const ai_real a = ai_real( 1.0 ) / ai_real(1.7320508);
-    const ai_real b = std::sqrt(( ai_real( 3.0 )- ai_real( 2.23606797))/ ai_real( 6.0) );
-    const ai_real c = std::sqrt(( ai_real( 3.0 )+ ai_real( 2.23606797f))/ ai_real( 6.0) );
-
-    const aiVector3D v0  = aiVector3D(a,a,a);
-    const aiVector3D v1  = aiVector3D(a,a,-a);
-    const aiVector3D v2  = aiVector3D(a,-a,a);
-    const aiVector3D v3  = aiVector3D(a,-a,-a);
-    const aiVector3D v4  = aiVector3D(-a,a,a);
-    const aiVector3D v5  = aiVector3D(-a,a,-a);
-    const aiVector3D v6  = aiVector3D(-a,-a,a);
-    const aiVector3D v7  = aiVector3D(-a,-a,-a);
-    const aiVector3D v8  = aiVector3D(b,c,0.0);
-    const aiVector3D v9  = aiVector3D(-b,c,0.0);
-    const aiVector3D v10 = aiVector3D(b,-c,0.0);
-    const aiVector3D v11 = aiVector3D(-b,-c,0.0);
-    const aiVector3D v12 = aiVector3D(c, 0.0, b);
-    const aiVector3D v13 = aiVector3D(c, 0.0, -b);
-    const aiVector3D v14 = aiVector3D(-c, 0.0, b);
-    const aiVector3D v15 = aiVector3D(-c, 0.0, -b);
-    const aiVector3D v16 = aiVector3D(0.0, b, c);
-    const aiVector3D v17 = aiVector3D(0.0, -b, c);
-    const aiVector3D v18 = aiVector3D(0.0, b, -c);
-    const aiVector3D v19 = aiVector3D(0.0, -b, -c);
-
-    ADD_PENTAGON(v0, v8, v9, v4, v16);
-    ADD_PENTAGON(v0, v12, v13, v1, v8);
-    ADD_PENTAGON(v0, v16, v17, v2, v12);
-    ADD_PENTAGON(v8, v1, v18, v5, v9);
-    ADD_PENTAGON(v12, v2, v10, v3, v13);
-    ADD_PENTAGON(v16, v4, v14, v6, v17);
-    ADD_PENTAGON(v9, v5, v15, v14, v4);
-
-    ADD_PENTAGON(v6, v11, v10, v2, v17);
-    ADD_PENTAGON(v3, v19, v18, v1, v13);
-    ADD_PENTAGON(v7, v15, v5, v18, v19);
-    ADD_PENTAGON(v7, v11, v6, v14, v15);
-    ADD_PENTAGON(v7, v19, v3, v10, v11);
-    return (polygons ? 5 : 3);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Build an octahedron with points.magnitude == 1
-unsigned int StandardShapes::MakeOctahedron(std::vector<aiVector3D>& positions)
-{
-    positions.reserve(positions.size()+24);
-
-    const aiVector3D v0  = aiVector3D(1.0, 0.0, 0.0) ;
-    const aiVector3D v1  = aiVector3D(-1.0, 0.0, 0.0);
-    const aiVector3D v2  = aiVector3D(0.0, 1.0, 0.0);
-    const aiVector3D v3  = aiVector3D(0.0, -1.0, 0.0);
-    const aiVector3D v4  = aiVector3D(0.0, 0.0, 1.0);
-    const aiVector3D v5  = aiVector3D(0.0, 0.0, -1.0);
-
-    ADD_TRIANGLE(v4,v0,v2);
-    ADD_TRIANGLE(v4,v2,v1);
-    ADD_TRIANGLE(v4,v1,v3);
-    ADD_TRIANGLE(v4,v3,v0);
-
-    ADD_TRIANGLE(v5,v2,v0);
-    ADD_TRIANGLE(v5,v1,v2);
-    ADD_TRIANGLE(v5,v3,v1);
-    ADD_TRIANGLE(v5,v0,v3);
-    return 3;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Build a tetrahedron with points.magnitude == 1
-unsigned int StandardShapes::MakeTetrahedron(std::vector<aiVector3D>& positions)
-{
-    positions.reserve(positions.size()+9);
-
-    const ai_real invThree = ai_real( 1.0 ) / ai_real( 3.0 );
-    const ai_real a = ai_real( 1.41421 ) * invThree;
-    const ai_real b = ai_real( 2.4494 ) * invThree;
-
-    const aiVector3D v0  = aiVector3D(0.0,0.0,1.0);
-    const aiVector3D v1  = aiVector3D(2*a,0,-invThree );
-    const aiVector3D v2  = aiVector3D(-a,b,-invThree );
-    const aiVector3D v3  = aiVector3D(-a,-b,-invThree );
-
-    ADD_TRIANGLE(v0,v1,v2);
-    ADD_TRIANGLE(v0,v2,v3);
-    ADD_TRIANGLE(v0,v3,v1);
-    ADD_TRIANGLE(v1,v3,v2);
-    return 3;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Build a hexahedron with points.magnitude == 1
-unsigned int StandardShapes::MakeHexahedron(std::vector<aiVector3D>& positions,
-    bool polygons /*= false*/)
-{
-    positions.reserve(positions.size()+36);
-    const ai_real length = ai_real(1.0)/ai_real(1.73205080);
-
-    const aiVector3D v0  = aiVector3D(-1.0,-1.0,-1.0)*length;
-    const aiVector3D v1  = aiVector3D(1.0,-1.0,-1.0)*length;
-    const aiVector3D v2  = aiVector3D(1.0,1.0,-1.0)*length;
-    const aiVector3D v3  = aiVector3D(-1.0,1.0,-1.0)*length;
-    const aiVector3D v4  = aiVector3D(-1.0,-1.0,1.0)*length;
-    const aiVector3D v5  = aiVector3D(1.0,-1.0,1.0)*length;
-    const aiVector3D v6  = aiVector3D(1.0,1.0,1.0)*length;
-    const aiVector3D v7  = aiVector3D(-1.0,1.0,1.0)*length;
-
-    ADD_QUAD(v0,v3,v2,v1);
-    ADD_QUAD(v0,v1,v5,v4);
-    ADD_QUAD(v0,v4,v7,v3);
-    ADD_QUAD(v6,v5,v1,v2);
-    ADD_QUAD(v6,v2,v3,v7);
-    ADD_QUAD(v6,v7,v4,v5);
-    return (polygons ? 4 : 3);
-}
-
-// Cleanup ...
-#undef ADD_TRIANGLE
-#undef ADD_QUAD
-#undef ADD_PENTAGON
-
-// ------------------------------------------------------------------------------------------------
-// Create a subdivision sphere
-void StandardShapes::MakeSphere(unsigned int    tess,
-    std::vector<aiVector3D>& positions)
-{
-    // Reserve enough storage. Every subdivision
-    // splits each triangle in 4, the icosahedron consists of 60 verts
-    positions.reserve(positions.size()+60 * integer_pow(4, tess));
-
-    // Construct an icosahedron to start with
-    MakeIcosahedron(positions);
-
-    // ... and subdivide it until the requested output
-    // tessellation is reached
-    for (unsigned int i = 0; i<tess;++i)
-        Subdivide(positions);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Build a cone
-void StandardShapes::MakeCone(ai_real height,ai_real radius1,
-    ai_real radius2,unsigned int tess,
-    std::vector<aiVector3D>& positions,bool bOpen /*= false */)
-{
-    // Sorry, a cone with less than 3 segments makes ABSOLUTELY NO SENSE
-    if (tess < 3 || !height)
-        return;
-
-    size_t old = positions.size();
-
-    // No negative radii
-    radius1 = std::fabs(radius1);
-    radius2 = std::fabs(radius2);
-
-    ai_real halfHeight = height / ai_real(2.0);
-
-    // radius1 is always the smaller one
-    if (radius2 > radius1)
-    {
-        std::swap(radius2,radius1);
-        halfHeight = -halfHeight;
-    }
-    else old = SIZE_MAX;
-
-    // Use a large epsilon to check whether the cone is pointy
-    if (radius1 < (radius2-radius1)*10e-3)radius1 = 0.0;
-
-    // We will need 3*2 verts per segment + 3*2 verts per segment
-    // if the cone is closed
-    const unsigned int mem = tess*6 + (!bOpen ? tess*3 * (radius1 ? 2 : 1) : 0);
-    positions.reserve(positions.size () + mem);
-
-    // Now construct all segments
-    const ai_real angle_delta = (ai_real)AI_MATH_TWO_PI / tess;
-    const ai_real angle_max   = (ai_real)AI_MATH_TWO_PI;
-
-    ai_real s = 1.0; // std::cos(angle == 0);
-    ai_real t = 0.0; // std::sin(angle == 0);
-
-    for (ai_real angle = 0.0; angle < angle_max; )
-    {
-        const aiVector3D v1 = aiVector3D (s * radius1, -halfHeight, t * radius1 );
-        const aiVector3D v2 = aiVector3D (s * radius2,  halfHeight, t * radius2 );
-
-        const ai_real next = angle + angle_delta;
-        ai_real s2 = std::cos(next);
-        ai_real t2 = std::sin(next);
-
-        const aiVector3D v3 = aiVector3D (s2 * radius2,  halfHeight, t2 * radius2 );
-        const aiVector3D v4 = aiVector3D (s2 * radius1, -halfHeight, t2 * radius1 );
-
-        positions.push_back(v1);
-        positions.push_back(v2);
-        positions.push_back(v3);
-        positions.push_back(v4);
-        positions.push_back(v1);
-        positions.push_back(v3);
-
-        if (!bOpen)
-        {
-            // generate the end 'cap'
-            positions.push_back(aiVector3D(s * radius2,  halfHeight, t * radius2 ));
-            positions.push_back(aiVector3D(s2 * radius2,  halfHeight, t2 * radius2 ));
-            positions.push_back(aiVector3D(0.0, halfHeight, 0.0));
-
-
-            if (radius1)
-            {
-                // generate the other end 'cap'
-                positions.push_back(aiVector3D(s * radius1,  -halfHeight, t * radius1 ));
-                positions.push_back(aiVector3D(s2 * radius1,  -halfHeight, t2 * radius1 ));
-                positions.push_back(aiVector3D(0.0, -halfHeight, 0.0));
-
-            }
-        }
-        s = s2;
-        t = t2;
-        angle = next;
-    }
-
-    // Need to flip face order?
-    if ( SIZE_MAX != old )  {
-        for (size_t p = old; p < positions.size();p += 3) {
-            std::swap(positions[p],positions[p+1]);
-        }
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-// Build a circle
-void StandardShapes::MakeCircle(ai_real radius, unsigned int tess,
-    std::vector<aiVector3D>& positions)
-{
-    // Sorry, a circle with less than 3 segments makes ABSOLUTELY NO SENSE
-    if (tess < 3 || !radius)
-        return;
-
-    radius = std::fabs(radius);
-
-    // We will need 3 vertices per segment
-    positions.reserve(positions.size()+tess*3);
-
-    const ai_real angle_delta = (ai_real)AI_MATH_TWO_PI / tess;
-    const ai_real angle_max   = (ai_real)AI_MATH_TWO_PI;
-
-    ai_real s = 1.0; // std::cos(angle == 0);
-    ai_real t = 0.0; // std::sin(angle == 0);
-
-    for (ai_real angle = 0.0; angle < angle_max;  )
-    {
-        positions.push_back(aiVector3D(s * radius,0.0,t * radius));
-        angle += angle_delta;
-        s = std::cos(angle);
-        t = std::sin(angle);
-        positions.push_back(aiVector3D(s * radius,0.0,t * radius));
-
-        positions.push_back(aiVector3D(0.0,0.0,0.0));
-    }
-}
-
-} // ! Assimp

+ 0 - 101
thirdparty/assimp/code/Common/StdOStreamLogStream.h

@@ -1,101 +0,0 @@
-/*
----------------------------------------------------------------------------
-Open Asset Import Library (assimp)
----------------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the following
-conditions are met:
-
-* Redistributions of source code must retain the above
-copyright notice, this list of conditions and the
-following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the
-following disclaimer in the documentation and/or other
-materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-contributors may be used to endorse or promote products
-derived from this software without specific prior
-written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------------
-*/
-
-/** @file  StdOStreamLogStream.h
-*  @brief Implementation of StdOStreamLogStream
-*/
-
-#ifndef AI_STROSTREAMLOGSTREAM_H_INC
-#define AI_STROSTREAMLOGSTREAM_H_INC
-
-#include <assimp/LogStream.hpp>
-#include <ostream>
-
-namespace Assimp    {
-
-// ---------------------------------------------------------------------------
-/** @class  StdOStreamLogStream
- *  @brief  Logs into a std::ostream
- */
-class StdOStreamLogStream : public LogStream {
-public:
-    /** @brief  Construction from an existing std::ostream
-     *  @param _ostream Output stream to be used
-    */
-    explicit StdOStreamLogStream(std::ostream& _ostream);
-
-    /** @brief  Destructor  */
-    ~StdOStreamLogStream();
-
-    /** @brief  Writer  */
-    void write(const char* message);
-
-private:
-    std::ostream& mOstream;
-};
-
-// ---------------------------------------------------------------------------
-//  Default constructor
-inline StdOStreamLogStream::StdOStreamLogStream(std::ostream& _ostream)
-: mOstream   (_ostream){
-    // empty
-}
-
-// ---------------------------------------------------------------------------
-//  Default constructor
-inline StdOStreamLogStream::~StdOStreamLogStream() {
-    // empty
-}
-
-// ---------------------------------------------------------------------------
-//  Write method
-inline void StdOStreamLogStream::write(const char* message) {
-    mOstream << message;
-    mOstream.flush();
-}
-
-// ---------------------------------------------------------------------------
-
-}   // Namespace Assimp
-
-#endif // guard

+ 0 - 589
thirdparty/assimp/code/Common/Subdivision.cpp

@@ -1,589 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, 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 <assimp/Subdivision.h>
-#include <assimp/SceneCombiner.h>
-#include <assimp/SpatialSort.h>
-#include <assimp/Vertex.h>
-#include <assimp/ai_assert.h>
-
-#include "PostProcessing/ProcessHelper.h"
-
-#include <stdio.h>
-
-using namespace Assimp;
-void mydummy() {}
-
-// ------------------------------------------------------------------------------------------------
-/** Subdivider stub class to implement the Catmull-Clarke subdivision algorithm. The
- *  implementation is basing on recursive refinement. Directly evaluating the result is also
- *  possible and much quicker, but it depends on lengthy matrix lookup tables. */
-// ------------------------------------------------------------------------------------------------
-class CatmullClarkSubdivider : public Subdivider {
-public:
-    void Subdivide (aiMesh* mesh, aiMesh*& out, unsigned int num, bool discard_input);
-    void Subdivide (aiMesh** smesh, size_t nmesh,
-        aiMesh** out, unsigned int num, bool discard_input);
-
-    // ---------------------------------------------------------------------------
-    /** Intermediate description of an edge between two corners of a polygon*/
-    // ---------------------------------------------------------------------------
-    struct Edge
-    {
-        Edge()
-            : ref(0)
-        {}
-        Vertex edge_point, midpoint;
-        unsigned int ref;
-    };
-
-    typedef std::vector<unsigned int> UIntVector;
-    typedef std::map<uint64_t,Edge> EdgeMap;
-
-    // ---------------------------------------------------------------------------
-    // Hashing function to derive an index into an #EdgeMap from two given
-    // 'unsigned int' vertex coordinates (!!distinct coordinates - same
-    // vertex position == same index!!).
-    // NOTE - this leads to rare hash collisions if a) sizeof(unsigned int)>4
-    // and (id[0]>2^32-1 or id[0]>2^32-1).
-    // MAKE_EDGE_HASH() uses temporaries, so INIT_EDGE_HASH() needs to be put
-    // at the head of every function which is about to use MAKE_EDGE_HASH().
-    // Reason is that the hash is that hash construction needs to hold the
-    // invariant id0<id1 to identify an edge - else two hashes would refer
-    // to the same edge.
-    // ---------------------------------------------------------------------------
-#define MAKE_EDGE_HASH(id0,id1) (eh_tmp0__=id0,eh_tmp1__=id1,\
-    (eh_tmp0__<eh_tmp1__?std::swap(eh_tmp0__,eh_tmp1__):mydummy()),(uint64_t)eh_tmp0__^((uint64_t)eh_tmp1__<<32u))
-
-
-#define INIT_EDGE_HASH_TEMPORARIES()\
-    unsigned int eh_tmp0__, eh_tmp1__;
-
-private:
-    void InternSubdivide (const aiMesh* const * smesh,
-        size_t nmesh,aiMesh** out, unsigned int num);
-};
-
-
-// ------------------------------------------------------------------------------------------------
-// Construct a subdivider of a specific type
-Subdivider* Subdivider::Create (Algorithm algo)
-{
-    switch (algo)
-    {
-    case CATMULL_CLARKE:
-        return new CatmullClarkSubdivider();
-    };
-
-    ai_assert(false);
-    return NULL; // shouldn't happen
-}
-
-// ------------------------------------------------------------------------------------------------
-// Call the Catmull Clark subdivision algorithm for one mesh
-void  CatmullClarkSubdivider::Subdivide (
-    aiMesh* mesh,
-    aiMesh*& out,
-    unsigned int num,
-    bool discard_input
-    )
-{
-    ai_assert(mesh != out);
-    
-    Subdivide(&mesh,1,&out,num,discard_input);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Call the Catmull Clark subdivision algorithm for multiple meshes
-void CatmullClarkSubdivider::Subdivide (
-    aiMesh** smesh,
-    size_t nmesh,
-    aiMesh** out,
-    unsigned int num,
-    bool discard_input
-    )
-{
-    ai_assert( NULL != smesh );
-    ai_assert( NULL != out );
-
-    // course, both regions may not overlap
-    ai_assert(smesh<out || smesh+nmesh>out+nmesh);
-    if (!num) {
-        // No subdivision at all. Need to copy all the meshes .. argh.
-        if (discard_input) {
-            for (size_t s = 0; s < nmesh; ++s) {
-                out[s] = smesh[s];
-                smesh[s] = NULL;
-            }
-        }
-        else {
-            for (size_t s = 0; s < nmesh; ++s) {
-                SceneCombiner::Copy(out+s,smesh[s]);
-            }
-        }
-        return;
-    }
-
-    std::vector<aiMesh*> inmeshes;
-    std::vector<aiMesh*> outmeshes;
-    std::vector<unsigned int> maptbl;
-
-    inmeshes.reserve(nmesh);
-    outmeshes.reserve(nmesh);
-    maptbl.reserve(nmesh);
-
-    // Remove pure line and point meshes from the working set to reduce the
-    // number of edge cases the subdivider is forced to deal with. Line and
-    // point meshes are simply passed through.
-    for (size_t s = 0; s < nmesh; ++s) {
-        aiMesh* i = smesh[s];
-        // FIX - mPrimitiveTypes might not yet be initialized
-        if (i->mPrimitiveTypes && (i->mPrimitiveTypes & (aiPrimitiveType_LINE|aiPrimitiveType_POINT))==i->mPrimitiveTypes) {
-            ASSIMP_LOG_DEBUG("Catmull-Clark Subdivider: Skipping pure line/point mesh");
-
-            if (discard_input) {
-                out[s] = i;
-                smesh[s] = NULL;
-            }
-            else {
-                SceneCombiner::Copy(out+s,i);
-            }
-            continue;
-        }
-
-        outmeshes.push_back(NULL);inmeshes.push_back(i);
-        maptbl.push_back(static_cast<unsigned int>(s));
-    }
-
-    // Do the actual subdivision on the preallocated storage. InternSubdivide
-    // *always* assumes that enough storage is available, it does not bother
-    // checking any ranges.
-    ai_assert(inmeshes.size()==outmeshes.size()&&inmeshes.size()==maptbl.size());
-    if (inmeshes.empty()) {
-        ASSIMP_LOG_WARN("Catmull-Clark Subdivider: Pure point/line scene, I can't do anything");
-        return;
-    }
-    InternSubdivide(&inmeshes.front(),inmeshes.size(),&outmeshes.front(),num);
-    for (unsigned int i = 0; i < maptbl.size(); ++i) {
-        ai_assert(nullptr != outmeshes[i]);
-        out[maptbl[i]] = outmeshes[i];
-    }
-
-    if (discard_input) {
-        for (size_t s = 0; s < nmesh; ++s) {
-            delete smesh[s];
-        }
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-// Note - this is an implementation of the standard (recursive) Cm-Cl algorithm without further
-// optimizations (except we're using some nice LUTs). A description of the algorithm can be found
-// here: http://en.wikipedia.org/wiki/Catmull-Clark_subdivision_surface
-//
-// The code is mostly O(n), however parts are O(nlogn) which is therefore the algorithm's
-// expected total runtime complexity. The implementation is able to work in-place on the same
-// mesh arrays. Calling #InternSubdivide() directly is not encouraged. The code can operate
-// in-place unless 'smesh' and 'out' are equal (no strange overlaps or reorderings).
-// Previous data is replaced/deleted then.
-// ------------------------------------------------------------------------------------------------
-void CatmullClarkSubdivider::InternSubdivide (
-    const aiMesh* const * smesh,
-    size_t nmesh,
-    aiMesh** out,
-    unsigned int num
-    )
-{
-    ai_assert(NULL != smesh && NULL != out);
-    INIT_EDGE_HASH_TEMPORARIES();
-
-    // no subdivision requested or end of recursive refinement
-    if (!num) {
-        return;
-    }
-
-    UIntVector maptbl;
-    SpatialSort spatial;
-
-    // ---------------------------------------------------------------------
-    // 0. Offset table to index all meshes continuously, generate a spatially
-    // sorted representation of all vertices in all meshes.
-    // ---------------------------------------------------------------------
-    typedef std::pair<unsigned int,unsigned int> IntPair;
-    std::vector<IntPair> moffsets(nmesh);
-    unsigned int totfaces = 0, totvert = 0;
-    for (size_t t = 0; t < nmesh; ++t) {
-        const aiMesh* mesh = smesh[t];
-
-        spatial.Append(mesh->mVertices,mesh->mNumVertices,sizeof(aiVector3D),false);
-        moffsets[t] = IntPair(totfaces,totvert);
-
-        totfaces += mesh->mNumFaces;
-        totvert  += mesh->mNumVertices;
-    }
-
-    spatial.Finalize();
-    const unsigned int num_unique = spatial.GenerateMappingTable(maptbl,ComputePositionEpsilon(smesh,nmesh));
-
-
-#define FLATTEN_VERTEX_IDX(mesh_idx, vert_idx) (moffsets[mesh_idx].second+vert_idx)
-#define   FLATTEN_FACE_IDX(mesh_idx, face_idx) (moffsets[mesh_idx].first+face_idx)
-
-    // ---------------------------------------------------------------------
-    // 1. Compute the centroid point for all faces
-    // ---------------------------------------------------------------------
-    std::vector<Vertex> centroids(totfaces);
-    unsigned int nfacesout = 0;
-    for (size_t t = 0, n = 0; t < nmesh; ++t) {
-        const aiMesh* mesh = smesh[t];
-        for (unsigned int i = 0; i < mesh->mNumFaces;++i,++n)
-        {
-            const aiFace& face = mesh->mFaces[i];
-            Vertex& c = centroids[n];
-
-            for (unsigned int a = 0; a < face.mNumIndices;++a) {
-                c += Vertex(mesh,face.mIndices[a]);
-            }
-
-            c /= static_cast<float>(face.mNumIndices);
-            nfacesout += face.mNumIndices;
-        }
-    }
-
-    {
-    // we want edges to go away before the recursive calls so begin a new scope
-    EdgeMap edges;
-
-    // ---------------------------------------------------------------------
-    // 2. Set each edge point to be the average of all neighbouring
-    // face points and original points. Every edge exists twice
-    // if there is a neighboring face.
-    // ---------------------------------------------------------------------
-    for (size_t t = 0; t < nmesh; ++t) {
-        const aiMesh* mesh = smesh[t];
-
-        for (unsigned int i = 0; i < mesh->mNumFaces;++i)   {
-            const aiFace& face = mesh->mFaces[i];
-
-            for (unsigned int p =0; p< face.mNumIndices; ++p) {
-                const unsigned int id[] = {
-                    face.mIndices[p],
-                    face.mIndices[p==face.mNumIndices-1?0:p+1]
-                };
-                const unsigned int mp[] = {
-                    maptbl[FLATTEN_VERTEX_IDX(t,id[0])],
-                    maptbl[FLATTEN_VERTEX_IDX(t,id[1])]
-                };
-
-                Edge& e = edges[MAKE_EDGE_HASH(mp[0],mp[1])];
-                e.ref++;
-                if (e.ref<=2) {
-                    if (e.ref==1) { // original points (end points) - add only once
-                        e.edge_point = e.midpoint = Vertex(mesh,id[0])+Vertex(mesh,id[1]);
-                        e.midpoint *= 0.5f;
-                    }
-                    e.edge_point += centroids[FLATTEN_FACE_IDX(t,i)];
-                }
-            }
-        }
-    }
-
-    // ---------------------------------------------------------------------
-    // 3. Normalize edge points
-    // ---------------------------------------------------------------------
-    {unsigned int bad_cnt = 0;
-    for (EdgeMap::iterator it = edges.begin(); it != edges.end(); ++it) {
-        if ((*it).second.ref < 2) {
-            ai_assert((*it).second.ref);
-            ++bad_cnt;
-        }
-        (*it).second.edge_point *= 1.f/((*it).second.ref+2.f);
-    }
-
-    if (bad_cnt) {
-        // Report the number of bad edges. bad edges are referenced by less than two
-        // faces in the mesh. They occur at outer model boundaries in non-closed
-        // shapes.
-        ASSIMP_LOG_DEBUG_F("Catmull-Clark Subdivider: got ", bad_cnt, " bad edges touching only one face (totally ", 
-            static_cast<unsigned int>(edges.size()), " edges). ");
-    }}
-
-    // ---------------------------------------------------------------------
-    // 4. Compute a vertex-face adjacency table. We can't reuse the code
-    // from VertexTriangleAdjacency because we need the table for multiple
-    // meshes and out vertex indices need to be mapped to distinct values
-    // first.
-    // ---------------------------------------------------------------------
-    UIntVector faceadjac(nfacesout), cntadjfac(maptbl.size(),0), ofsadjvec(maptbl.size()+1,0); {
-    for (size_t t = 0; t < nmesh; ++t) {
-        const aiMesh* const minp = smesh[t];
-        for (unsigned int i = 0; i < minp->mNumFaces; ++i) {
-
-            const aiFace& f = minp->mFaces[i];
-            for (unsigned int n = 0; n < f.mNumIndices; ++n) {
-                ++cntadjfac[maptbl[FLATTEN_VERTEX_IDX(t,f.mIndices[n])]];
-            }
-        }
-    }
-    unsigned int cur = 0;
-    for (size_t i = 0; i < cntadjfac.size(); ++i) {
-        ofsadjvec[i+1] = cur;
-        cur += cntadjfac[i];
-    }
-    for (size_t t = 0; t < nmesh; ++t) {
-        const aiMesh* const minp = smesh[t];
-        for (unsigned int i = 0; i < minp->mNumFaces; ++i) {
-
-            const aiFace& f = minp->mFaces[i];
-            for (unsigned int n = 0; n < f.mNumIndices; ++n) {
-                faceadjac[ofsadjvec[1+maptbl[FLATTEN_VERTEX_IDX(t,f.mIndices[n])]]++] = FLATTEN_FACE_IDX(t,i);
-            }
-        }
-    }
-
-    // check the other way round for consistency
-#ifdef ASSIMP_BUILD_DEBUG
-
-    for (size_t t = 0; t < ofsadjvec.size()-1; ++t) {
-        for (unsigned int m = 0; m <  cntadjfac[t]; ++m) {
-            const unsigned int fidx = faceadjac[ofsadjvec[t]+m];
-            ai_assert(fidx < totfaces);
-            for (size_t n = 1; n < nmesh; ++n) {
-
-                if (moffsets[n].first > fidx) {
-                    const aiMesh* msh = smesh[--n];
-                    const aiFace& f = msh->mFaces[fidx-moffsets[n].first];
-
-                    bool haveit = false;
-                    for (unsigned int i = 0; i < f.mNumIndices; ++i) {
-                        if (maptbl[FLATTEN_VERTEX_IDX(n,f.mIndices[i])]==(unsigned int)t) {
-                            haveit = true;
-                            break;
-                        }
-                    }
-                    ai_assert(haveit);
-                    if (!haveit) {
-                        ASSIMP_LOG_DEBUG("Catmull-Clark Subdivider: Index not used");
-                    }
-                    break;
-                }
-            }
-        }
-    }
-
-#endif
-    }
-
-#define GET_ADJACENT_FACES_AND_CNT(vidx,fstartout,numout) \
-    fstartout = &faceadjac[ofsadjvec[vidx]], numout = cntadjfac[vidx]
-
-    typedef std::pair<bool,Vertex> TouchedOVertex;
-    std::vector<TouchedOVertex > new_points(num_unique,TouchedOVertex(false,Vertex()));
-    // ---------------------------------------------------------------------
-    // 5. Spawn a quad from each face point to the corresponding edge points
-    // the original points being the fourth quad points.
-    // ---------------------------------------------------------------------
-    for (size_t t = 0; t < nmesh; ++t) {
-        const aiMesh* const minp = smesh[t];
-        aiMesh* const mout = out[t] = new aiMesh();
-
-        for (unsigned int a  = 0; a < minp->mNumFaces; ++a) {
-            mout->mNumFaces += minp->mFaces[a].mNumIndices;
-        }
-
-        // We need random access to the old face buffer, so reuse is not possible.
-        mout->mFaces = new aiFace[mout->mNumFaces];
-
-        mout->mNumVertices = mout->mNumFaces*4;
-        mout->mVertices = new aiVector3D[mout->mNumVertices];
-
-        // quads only, keep material index
-        mout->mPrimitiveTypes = aiPrimitiveType_POLYGON;
-        mout->mMaterialIndex = minp->mMaterialIndex;
-
-        if (minp->HasNormals()) {
-            mout->mNormals = new aiVector3D[mout->mNumVertices];
-        }
-
-        if (minp->HasTangentsAndBitangents()) {
-            mout->mTangents = new aiVector3D[mout->mNumVertices];
-            mout->mBitangents = new aiVector3D[mout->mNumVertices];
-        }
-
-        for(unsigned int i = 0; minp->HasTextureCoords(i); ++i) {
-            mout->mTextureCoords[i] = new aiVector3D[mout->mNumVertices];
-            mout->mNumUVComponents[i] = minp->mNumUVComponents[i];
-        }
-
-        for(unsigned int i = 0; minp->HasVertexColors(i); ++i) {
-            mout->mColors[i] = new aiColor4D[mout->mNumVertices];
-        }
-
-        mout->mNumVertices = mout->mNumFaces<<2u;
-        for (unsigned int i = 0, v = 0, n = 0; i < minp->mNumFaces;++i) {
-
-            const aiFace& face = minp->mFaces[i];
-            for (unsigned int a = 0; a < face.mNumIndices;++a)  {
-
-                // Get a clean new face.
-                aiFace& faceOut = mout->mFaces[n++];
-                faceOut.mIndices = new unsigned int [faceOut.mNumIndices = 4];
-
-                // Spawn a new quadrilateral (ccw winding) for this original point between:
-                // a) face centroid
-                centroids[FLATTEN_FACE_IDX(t,i)].SortBack(mout,faceOut.mIndices[0]=v++);
-
-                // b) adjacent edge on the left, seen from the centroid
-                const Edge& e0 = edges[MAKE_EDGE_HASH(maptbl[FLATTEN_VERTEX_IDX(t,face.mIndices[a])],
-                    maptbl[FLATTEN_VERTEX_IDX(t,face.mIndices[a==face.mNumIndices-1?0:a+1])
-                    ])];  // fixme: replace with mod face.mNumIndices?
-
-                // c) adjacent edge on the right, seen from the centroid
-                const Edge& e1 = edges[MAKE_EDGE_HASH(maptbl[FLATTEN_VERTEX_IDX(t,face.mIndices[a])],
-                    maptbl[FLATTEN_VERTEX_IDX(t,face.mIndices[!a?face.mNumIndices-1:a-1])
-                    ])];  // fixme: replace with mod face.mNumIndices?
-
-                e0.edge_point.SortBack(mout,faceOut.mIndices[3]=v++);
-                e1.edge_point.SortBack(mout,faceOut.mIndices[1]=v++);
-
-                // d= original point P with distinct index i
-                // F := 0
-                // R := 0
-                // n := 0
-                // for each face f containing i
-                //    F := F+ centroid of f
-                //    R := R+ midpoint of edge of f from i to i+1
-                //    n := n+1
-                //
-                // (F+2R+(n-3)P)/n
-                const unsigned int org = maptbl[FLATTEN_VERTEX_IDX(t,face.mIndices[a])];
-                TouchedOVertex& ov = new_points[org];
-
-                if (!ov.first) {
-                    ov.first = true;
-
-                    const unsigned int* adj; unsigned int cnt;
-                    GET_ADJACENT_FACES_AND_CNT(org,adj,cnt);
-
-                    if (cnt < 3) {
-                        ov.second = Vertex(minp,face.mIndices[a]);
-                    }
-                    else {
-
-                        Vertex F,R;
-                        for (unsigned int o = 0; o < cnt; ++o) {
-                            ai_assert(adj[o] < totfaces);
-                            F += centroids[adj[o]];
-
-                            // adj[0] is a global face index - search the face in the mesh list
-                            const aiMesh* mp = NULL;
-                            size_t nidx;
-
-                            if (adj[o] < moffsets[0].first) {
-                                mp = smesh[nidx=0];
-                            }
-                            else {
-                                for (nidx = 1; nidx<= nmesh; ++nidx) {
-                                    if (nidx == nmesh ||moffsets[nidx].first > adj[o]) {
-                                        mp = smesh[--nidx];
-                                        break;
-                                    }
-                                }
-                            }
-
-                            ai_assert(adj[o]-moffsets[nidx].first < mp->mNumFaces);
-                            const aiFace& f = mp->mFaces[adj[o]-moffsets[nidx].first];
-                            bool haveit = false;
-
-                            // find our original point in the face
-                            for (unsigned int m = 0; m < f.mNumIndices; ++m) {
-                                if (maptbl[FLATTEN_VERTEX_IDX(nidx,f.mIndices[m])] == org) {
-
-                                    // add *both* edges. this way, we can be sure that we add
-                                    // *all* adjacent edges to R. In a closed shape, every
-                                    // edge is added twice - so we simply leave out the
-                                    // factor 2.f in the amove formula and get the right
-                                    // result.
-
-                                    const Edge& c0 = edges[MAKE_EDGE_HASH(org,maptbl[FLATTEN_VERTEX_IDX(
-                                        nidx,f.mIndices[!m?f.mNumIndices-1:m-1])])];
-                                    // fixme: replace with mod face.mNumIndices?
-
-                                    const Edge& c1 = edges[MAKE_EDGE_HASH(org,maptbl[FLATTEN_VERTEX_IDX(
-                                        nidx,f.mIndices[m==f.mNumIndices-1?0:m+1])])];
-                                    // fixme: replace with mod face.mNumIndices?
-                                    R += c0.midpoint+c1.midpoint;
-
-                                    haveit = true;
-                                    break;
-                                }
-                            }
-
-                            // this invariant *must* hold if the vertex-to-face adjacency table is valid
-                            ai_assert(haveit);
-                            if ( !haveit ) {
-                                ASSIMP_LOG_WARN( "OBJ: no name for material library specified." );
-                            }
-                        }
-
-                        const float div = static_cast<float>(cnt), divsq = 1.f/(div*div);
-                        ov.second = Vertex(minp,face.mIndices[a])*((div-3.f) / div) + R*divsq + F*divsq;
-                    }
-                }
-                ov.second.SortBack(mout,faceOut.mIndices[2]=v++);
-            }
-        }
-    }
-    }  // end of scope for edges, freeing its memory
-
-    // ---------------------------------------------------------------------
-    // 7. Apply the next subdivision step.
-    // ---------------------------------------------------------------------
-    if (num != 1) {
-        std::vector<aiMesh*> tmp(nmesh);
-        InternSubdivide (out,nmesh,&tmp.front(),num-1);
-        for (size_t i = 0; i < nmesh; ++i) {
-            delete out[i];
-            out[i] = tmp[i];
-        }
-    }
-}

+ 0 - 248
thirdparty/assimp/code/Common/TargetAnimation.cpp

@@ -1,248 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, 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 "TargetAnimation.h"
-#include <algorithm>
-#include <assimp/ai_assert.h>
-
-using namespace Assimp;
-
-
-// ------------------------------------------------------------------------------------------------
-KeyIterator::KeyIterator(const std::vector<aiVectorKey>* _objPos,
-    const std::vector<aiVectorKey>* _targetObjPos,
-    const aiVector3D*  defaultObjectPos /*= NULL*/,
-    const aiVector3D*  defaultTargetPos /*= NULL*/)
-
-        :   reachedEnd      (false)
-        ,   curTime         (-1.)
-        ,   objPos          (_objPos)
-        ,   targetObjPos    (_targetObjPos)
-        ,   nextObjPos      (0)
-        ,   nextTargetObjPos(0)
-{
-    // Generate default transformation tracks if necessary
-    if (!objPos || objPos->empty())
-    {
-        defaultObjPos.resize(1);
-        defaultObjPos.front().mTime  = 10e10;
-
-        if (defaultObjectPos)
-            defaultObjPos.front().mValue = *defaultObjectPos;
-
-        objPos = & defaultObjPos;
-    }
-    if (!targetObjPos || targetObjPos->empty())
-    {
-        defaultTargetObjPos.resize(1);
-        defaultTargetObjPos.front().mTime  = 10e10;
-
-        if (defaultTargetPos)
-            defaultTargetObjPos.front().mValue = *defaultTargetPos;
-
-        targetObjPos = & defaultTargetObjPos;
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-template <class T>
-inline T Interpolate(const T& one, const T& two, ai_real val)
-{
-    return one + (two-one)*val;
-}
-
-// ------------------------------------------------------------------------------------------------
-void KeyIterator::operator ++()
-{
-    // If we are already at the end of all keyframes, return
-    if (reachedEnd) {
-        return;
-    }
-
-    // Now search in all arrays for the time value closest
-    // to our current position on the time line
-    double d0,d1;
-
-    d0 = objPos->at      ( std::min ( nextObjPos, static_cast<unsigned int>(objPos->size()-1))             ).mTime;
-    d1 = targetObjPos->at( std::min ( nextTargetObjPos, static_cast<unsigned int>(targetObjPos->size()-1)) ).mTime;
-
-    // Easiest case - all are identical. In this
-    // case we don't need to interpolate so we can
-    // return earlier
-    if ( d0 == d1 )
-    {
-        curTime = d0;
-        curPosition = objPos->at(nextObjPos).mValue;
-        curTargetPosition = targetObjPos->at(nextTargetObjPos).mValue;
-
-        // increment counters
-        if (objPos->size() != nextObjPos-1)
-            ++nextObjPos;
-
-        if (targetObjPos->size() != nextTargetObjPos-1)
-            ++nextTargetObjPos;
-    }
-
-    // An object position key is closest to us
-    else if (d0 < d1)
-    {
-        curTime = d0;
-
-        // interpolate the other
-        if (1 == targetObjPos->size() || !nextTargetObjPos) {
-            curTargetPosition = targetObjPos->at(0).mValue;
-        }
-        else
-        {
-            const aiVectorKey& last  = targetObjPos->at(nextTargetObjPos);
-            const aiVectorKey& first = targetObjPos->at(nextTargetObjPos-1);
-
-            curTargetPosition = Interpolate(first.mValue, last.mValue, (ai_real) (
-                (curTime-first.mTime) / (last.mTime-first.mTime) ));
-        }
-
-        if (objPos->size() != nextObjPos-1)
-            ++nextObjPos;
-    }
-    // A target position key is closest to us
-    else
-    {
-        curTime = d1;
-
-        // interpolate the other
-        if (1 == objPos->size() || !nextObjPos) {
-            curPosition = objPos->at(0).mValue;
-        }
-        else
-        {
-            const aiVectorKey& last  = objPos->at(nextObjPos);
-            const aiVectorKey& first = objPos->at(nextObjPos-1);
-
-            curPosition = Interpolate(first.mValue, last.mValue, (ai_real) (
-                (curTime-first.mTime) / (last.mTime-first.mTime)));
-        }
-
-        if (targetObjPos->size() != nextTargetObjPos-1)
-            ++nextTargetObjPos;
-    }
-
-    if (nextObjPos >= objPos->size()-1 &&
-        nextTargetObjPos >= targetObjPos->size()-1)
-    {
-        // We reached the very last keyframe
-        reachedEnd = true;
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-void TargetAnimationHelper::SetTargetAnimationChannel (
-    const std::vector<aiVectorKey>* _targetPositions)
-{
-    ai_assert(NULL != _targetPositions);
-    targetPositions = _targetPositions;
-}
-
-// ------------------------------------------------------------------------------------------------
-void TargetAnimationHelper::SetMainAnimationChannel (
-    const std::vector<aiVectorKey>* _objectPositions)
-{
-    ai_assert(NULL != _objectPositions);
-    objectPositions = _objectPositions;
-}
-
-// ------------------------------------------------------------------------------------------------
-void TargetAnimationHelper::SetFixedMainAnimationChannel(
-    const aiVector3D& fixed)
-{
-    objectPositions = NULL; // just to avoid confusion
-    fixedMain = fixed;
-}
-
-// ------------------------------------------------------------------------------------------------
-void TargetAnimationHelper::Process(std::vector<aiVectorKey>* distanceTrack)
-{
-    ai_assert(NULL != targetPositions && NULL != distanceTrack);
-
-    // TODO: in most cases we won't need the extra array
-    std::vector<aiVectorKey>  real;
-
-    std::vector<aiVectorKey>* fill = (distanceTrack == objectPositions ? &real : distanceTrack);
-    fill->reserve(std::max( objectPositions->size(), targetPositions->size() ));
-
-    // Iterate through all object keys and interpolate their values if necessary.
-    // Then get the corresponding target position, compute the difference
-    // vector between object and target position. Then compute a rotation matrix
-    // that rotates the base vector of the object coordinate system at that time
-    // to match the diff vector.
-
-    KeyIterator iter(objectPositions,targetPositions,&fixedMain);
-    for (;!iter.Finished();++iter)
-    {
-        const aiVector3D&  position  = iter.GetCurPosition();
-        const aiVector3D&  tposition = iter.GetCurTargetPosition();
-
-        // diff vector
-        aiVector3D diff = tposition - position;
-        ai_real f = diff.Length();
-
-        // output distance vector
-        if (f)
-        {
-            fill->push_back(aiVectorKey());
-            aiVectorKey& v = fill->back();
-            v.mTime  = iter.GetCurTime();
-            v.mValue = diff;
-
-            diff /= f;
-        }
-        else
-        {
-            // FIXME: handle this
-        }
-
-        // diff is now the vector in which our camera is pointing
-    }
-
-    if (real.size()) {
-        *distanceTrack = real;
-    }
-}

+ 0 - 183
thirdparty/assimp/code/Common/TargetAnimation.h

@@ -1,183 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file Defines a helper class for the ASE and 3DS loaders to
- help them compute camera and spot light animation channels */
-#ifndef AI_TARGET_ANIMATION_H_INC
-#define AI_TARGET_ANIMATION_H_INC
-
-#include <assimp/anim.h>
-#include <vector>
-
-namespace Assimp    {
-
-
-
-// ---------------------------------------------------------------------------
-/** Helper class to iterate through all keys in an animation channel.
- *
- *  Missing tracks are interpolated. This is a helper class for
- *  TargetAnimationHelper, but it can be freely used for other purposes.
-*/
-class KeyIterator
-{
-public:
-
-
-    // ------------------------------------------------------------------
-    /** Constructs a new key iterator
-     *
-     *  @param _objPos Object position track. May be NULL.
-     *  @param _targetObjPos Target object position track. May be NULL.
-     *  @param defaultObjectPos Default object position to be used if
-     *    no animated track is available. May be NULL.
-     *  @param defaultTargetPos Default target position to be used if
-     *    no animated track is available. May be NULL.
-     */
-    KeyIterator(const std::vector<aiVectorKey>* _objPos,
-        const std::vector<aiVectorKey>* _targetObjPos,
-        const aiVector3D*  defaultObjectPos = NULL,
-        const aiVector3D*  defaultTargetPos = NULL);
-
-    // ------------------------------------------------------------------
-    /** Returns true if all keys have been processed
-     */
-    bool Finished() const
-        {return reachedEnd;}
-
-    // ------------------------------------------------------------------
-    /** Increment the iterator
-     */
-    void operator++();
-    inline void operator++(int)
-        {return ++(*this);}
-
-
-
-    // ------------------------------------------------------------------
-    /** Getters to retrieve the current state of the iterator
-     */
-    inline const aiVector3D& GetCurPosition() const
-        {return curPosition;}
-
-    inline const aiVector3D& GetCurTargetPosition() const
-        {return curTargetPosition;}
-
-    inline double GetCurTime() const
-        {return curTime;}
-
-private:
-
-    //! Did we reach the end?
-    bool reachedEnd;
-
-    //! Represents the current position of the iterator
-    aiVector3D curPosition, curTargetPosition;
-
-    double curTime;
-
-    //! Input tracks and the next key to process
-    const std::vector<aiVectorKey>* objPos,*targetObjPos;
-
-    unsigned int nextObjPos, nextTargetObjPos;
-    std::vector<aiVectorKey> defaultObjPos,defaultTargetObjPos;
-};
-
-// ---------------------------------------------------------------------------
-/** Helper class for the 3DS and ASE loaders to compute camera and spot light
- *  animations.
- *
- * 3DS and ASE store the differently to Assimp - there is an animation
- * channel for the camera/spot light itself and a separate position
- * animation channels specifying the position of the camera/spot light
- * look-at target */
-class TargetAnimationHelper
-{
-public:
-
-    TargetAnimationHelper()
-        :   targetPositions     (NULL)
-        ,   objectPositions     (NULL)
-    {}
-
-
-    // ------------------------------------------------------------------
-    /** Sets the target animation channel
-     *
-     *  This channel specifies the position of the camera/spot light
-     *  target at a specific position.
-     *
-     *  @param targetPositions Translation channel*/
-    void SetTargetAnimationChannel (const
-        std::vector<aiVectorKey>* targetPositions);
-
-
-    // ------------------------------------------------------------------
-    /** Sets the main animation channel
-     *
-     *  @param objectPositions Translation channel */
-    void SetMainAnimationChannel ( const
-        std::vector<aiVectorKey>* objectPositions);
-
-    // ------------------------------------------------------------------
-    /** Sets the main animation channel to a fixed value
-     *
-     *  @param fixed Fixed value for the main animation channel*/
-    void SetFixedMainAnimationChannel(const aiVector3D& fixed);
-
-
-    // ------------------------------------------------------------------
-    /** Computes final animation channels
-     * @param distanceTrack Receive camera translation keys ... != NULL. */
-    void Process( std::vector<aiVectorKey>* distanceTrack );
-
-
-private:
-
-    const std::vector<aiVectorKey>* targetPositions,*objectPositions;
-    aiVector3D fixedMain;
-};
-
-
-} // ! end namespace Assimp
-
-#endif // include guard

+ 0 - 181
thirdparty/assimp/code/Common/Version.cpp

@@ -1,181 +0,0 @@
-/*
----------------------------------------------------------------------------
-Open Asset Import Library (assimp)
----------------------------------------------------------------------------
-
-Copyright (c) 2006-2019, 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.
----------------------------------------------------------------------------
-*/
-
-// Actually just a dummy, used by the compiler to build the precompiled header.
-
-#include <assimp/version.h>
-#include <assimp/scene.h>
-#include "ScenePrivate.h"
-
-#include "revision.h"
-
-// --------------------------------------------------------------------------------
-// Legal information string - don't remove this.
-static const char* LEGAL_INFORMATION =
-
-"Open Asset Import Library (Assimp).\n"
-"A free C/C++ library to import various 3D file formats into applications\n\n"
-
-"(c) 2006-2019, assimp team\n"
-"License under the terms and conditions of the 3-clause BSD license\n"
-"http://assimp.org\n"
-;
-
-// ------------------------------------------------------------------------------------------------
-// Get legal string
-ASSIMP_API const char*  aiGetLegalString  ()    {
-    return LEGAL_INFORMATION;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Get Assimp minor version
-ASSIMP_API unsigned int aiGetVersionMinor ()    {
-    return VER_MINOR;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Get Assimp major version
-ASSIMP_API unsigned int aiGetVersionMajor ()    {
-    return VER_MAJOR;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Get flags used for compilation
-ASSIMP_API unsigned int aiGetCompileFlags ()    {
-
-    unsigned int flags = 0;
-
-#ifdef ASSIMP_BUILD_BOOST_WORKAROUND
-    flags |= ASSIMP_CFLAGS_NOBOOST;
-#endif
-#ifdef ASSIMP_BUILD_SINGLETHREADED
-    flags |= ASSIMP_CFLAGS_SINGLETHREADED;
-#endif
-#ifdef ASSIMP_BUILD_DEBUG
-    flags |= ASSIMP_CFLAGS_DEBUG;
-#endif
-#ifdef ASSIMP_BUILD_DLL_EXPORT
-    flags |= ASSIMP_CFLAGS_SHARED;
-#endif
-#ifdef _STLPORT_VERSION
-    flags |= ASSIMP_CFLAGS_STLPORT;
-#endif
-
-    return flags;
-}
-
-// ------------------------------------------------------------------------------------------------
-ASSIMP_API unsigned int aiGetVersionRevision() {
-    return GitVersion;
-}
-
-ASSIMP_API const char *aiGetBranchName() {
-    return GitBranch;
-}
-
-// ------------------------------------------------------------------------------------------------
-ASSIMP_API aiScene::aiScene()
-: mFlags(0)
-, mRootNode(nullptr)
-, mNumMeshes(0)
-, mMeshes(nullptr)
-, mNumMaterials(0)
-, mMaterials(nullptr)
-, mNumAnimations(0)
-, mAnimations(nullptr)
-, mNumTextures(0)
-, mTextures(nullptr)
-, mNumLights(0)
-, mLights(nullptr)
-, mNumCameras(0)
-, mCameras(nullptr)
-, mMetaData(nullptr)
-, mPrivate(new Assimp::ScenePrivateData()) {
-	// empty
-}
-
-// ------------------------------------------------------------------------------------------------
-ASSIMP_API aiScene::~aiScene() {
-    // delete all sub-objects recursively
-    delete mRootNode;
-
-    // To make sure we won't crash if the data is invalid it's
-    // much better to check whether both mNumXXX and mXXX are
-    // valid instead of relying on just one of them.
-    if (mNumMeshes && mMeshes)
-        for( unsigned int a = 0; a < mNumMeshes; a++)
-            delete mMeshes[a];
-    delete [] mMeshes;
-
-    if (mNumMaterials && mMaterials) {
-        for (unsigned int a = 0; a < mNumMaterials; ++a ) {
-            delete mMaterials[ a ];
-        }
-    }
-    delete [] mMaterials;
-
-    if (mNumAnimations && mAnimations)
-        for( unsigned int a = 0; a < mNumAnimations; a++)
-            delete mAnimations[a];
-    delete [] mAnimations;
-
-    if (mNumTextures && mTextures)
-        for( unsigned int a = 0; a < mNumTextures; a++)
-            delete mTextures[a];
-    delete [] mTextures;
-
-    if (mNumLights && mLights)
-        for( unsigned int a = 0; a < mNumLights; a++)
-            delete mLights[a];
-    delete [] mLights;
-
-    if (mNumCameras && mCameras)
-        for( unsigned int a = 0; a < mNumCameras; a++)
-            delete mCameras[a];
-    delete [] mCameras;
-
-    aiMetadata::Dealloc(mMetaData);
-    mMetaData = nullptr;
-
-    delete static_cast<Assimp::ScenePrivateData*>( mPrivate );
-}
-

+ 0 - 134
thirdparty/assimp/code/Common/VertexTriangleAdjacency.cpp

@@ -1,134 +0,0 @@
-/*
----------------------------------------------------------------------------
-Open Asset Import Library (assimp)
----------------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the following
-conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------------
-*/
-
-/** @file Implementation of the VertexTriangleAdjacency helper class
- */
-
-// internal headers
-#include "VertexTriangleAdjacency.h"
-#include <assimp/mesh.h>
-
-using namespace Assimp;
-
-// ------------------------------------------------------------------------------------------------
-VertexTriangleAdjacency::VertexTriangleAdjacency(aiFace *pcFaces,
-    unsigned int iNumFaces,
-    unsigned int iNumVertices /*= 0*/,
-    bool bComputeNumTriangles /*= false*/)
-{
-    // compute the number of referenced vertices if it wasn't specified by the caller
-    const aiFace* const pcFaceEnd = pcFaces + iNumFaces;
-    if (!iNumVertices)  {
-        for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace)   {
-            ai_assert( nullptr != pcFace );
-            ai_assert(3 == pcFace->mNumIndices);
-            iNumVertices = std::max(iNumVertices,pcFace->mIndices[0]);
-            iNumVertices = std::max(iNumVertices,pcFace->mIndices[1]);
-            iNumVertices = std::max(iNumVertices,pcFace->mIndices[2]);
-        }
-    }
-
-    mNumVertices = iNumVertices;
-
-    unsigned int* pi;
-
-    // allocate storage
-    if (bComputeNumTriangles)   {
-        pi = mLiveTriangles = new unsigned int[iNumVertices+1];
-        ::memset(mLiveTriangles,0,sizeof(unsigned int)*(iNumVertices+1));
-        mOffsetTable = new unsigned int[iNumVertices+2]+1;
-    } else {
-        pi = mOffsetTable = new unsigned int[iNumVertices+2]+1;
-        ::memset(mOffsetTable,0,sizeof(unsigned int)*(iNumVertices+1));
-        mLiveTriangles = NULL; // important, otherwise the d'tor would crash
-    }
-
-    // get a pointer to the end of the buffer
-    unsigned int* piEnd = pi+iNumVertices;
-    *piEnd++ = 0u;
-
-    // first pass: compute the number of faces referencing each vertex
-    for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace)
-    {
-        unsigned nind = pcFace->mNumIndices;
-        unsigned * ind = pcFace->mIndices;
-        if (nind > 0) pi[ind[0]]++;
-        if (nind > 1) pi[ind[1]]++;
-        if (nind > 2) pi[ind[2]]++;
-    }
-
-    // second pass: compute the final offset table
-    unsigned int iSum = 0;
-    unsigned int* piCurOut = this->mOffsetTable;
-    for (unsigned int* piCur = pi; piCur != piEnd;++piCur,++piCurOut)   {
-
-        unsigned int iLastSum = iSum;
-        iSum += *piCur;
-        *piCurOut = iLastSum;
-    }
-    pi = this->mOffsetTable;
-
-    // third pass: compute the final table
-    this->mAdjacencyTable = new unsigned int[iSum];
-    iSum = 0;
-    for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace,++iSum)    {
-        unsigned nind = pcFace->mNumIndices;
-        unsigned * ind = pcFace->mIndices;
-
-        if (nind > 0) mAdjacencyTable[pi[ind[0]]++] = iSum;
-        if (nind > 1) mAdjacencyTable[pi[ind[1]]++] = iSum;
-        if (nind > 2) mAdjacencyTable[pi[ind[2]]++] = iSum;
-    }
-    // fourth pass: undo the offset computations made during the third pass
-    // We could do this in a separate buffer, but this would be TIMES slower.
-    --mOffsetTable;
-    *mOffsetTable = 0u;
-}
-// ------------------------------------------------------------------------------------------------
-VertexTriangleAdjacency::~VertexTriangleAdjacency()
-{
-    // delete allocated storage
-    delete[] mOffsetTable;
-    delete[] mAdjacencyTable;
-    delete[] mLiveTriangles;
-}

+ 0 - 117
thirdparty/assimp/code/Common/VertexTriangleAdjacency.h

@@ -1,117 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file Defines a helper class to compute a vertex-triangle adjacency map */
-#ifndef AI_VTADJACENCY_H_INC
-#define AI_VTADJACENCY_H_INC
-
-#include "BaseProcess.h"
-#include <assimp/types.h>
-#include <assimp/ai_assert.h>
-
-struct aiMesh;
-struct aiFace;
-
-namespace Assimp    {
-
-// --------------------------------------------------------------------------------------------
-/** @brief The VertexTriangleAdjacency class computes a vertex-triangle
- *  adjacency map from a given index buffer.
- *
- *  @note Although it is called #VertexTriangleAdjacency, the current version does also
- *    support arbitrary polygons. */
-// --------------------------------------------------------------------------------------------
-class ASSIMP_API VertexTriangleAdjacency {
-public:
-    // ----------------------------------------------------------------------------
-    /** @brief Construction from an existing index buffer
-     *  @param pcFaces Index buffer
-     *  @param iNumFaces Number of faces in the buffer
-     *  @param iNumVertices Number of referenced vertices. This value
-     *    is computed automatically if 0 is specified.
-     *  @param bComputeNumTriangles If you want the class to compute
-     *    a list containing the number of referenced triangles per vertex
-     *    per vertex - pass true.  */
-    VertexTriangleAdjacency(aiFace* pcFaces,unsigned int iNumFaces,
-        unsigned int iNumVertices = 0,
-        bool bComputeNumTriangles = true);
-
-    // ----------------------------------------------------------------------------
-    /** @brief Destructor */
-    ~VertexTriangleAdjacency();
-
-    // ----------------------------------------------------------------------------
-    /** @brief Get all triangles adjacent to a vertex
-     *  @param iVertIndex Index of the vertex
-     *  @return A pointer to the adjacency list. */
-    unsigned int* GetAdjacentTriangles(unsigned int iVertIndex) const {
-        ai_assert(iVertIndex < mNumVertices);
-        return &mAdjacencyTable[ mOffsetTable[iVertIndex]];
-    }
-
-    // ----------------------------------------------------------------------------
-    /** @brief Get the number of triangles that are referenced by
-     *    a vertex. This function returns a reference that can be modified
-     *  @param iVertIndex Index of the vertex
-     *  @return Number of referenced triangles */
-    unsigned int& GetNumTrianglesPtr(unsigned int iVertIndex) {
-        ai_assert( iVertIndex < mNumVertices );
-        ai_assert( nullptr != mLiveTriangles );
-        return mLiveTriangles[iVertIndex];
-    }
-
-    //! Offset table
-    unsigned int* mOffsetTable;
-
-    //! Adjacency table
-    unsigned int* mAdjacencyTable;
-
-    //! Table containing the number of referenced triangles per vertex
-    unsigned int* mLiveTriangles;
-
-    //! Debug: Number of referenced vertices
-    unsigned int mNumVertices;
-};
-
-} //! ns Assimp
-
-#endif // !! AI_VTADJACENCY_H_INC

+ 0 - 95
thirdparty/assimp/code/Common/Win32DebugLogStream.h

@@ -1,95 +0,0 @@
-/*
----------------------------------------------------------------------------
-Open Asset Import Library (assimp)
----------------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the following
-conditions are met:
-
-* Redistributions of source code must retain the above
-copyright notice, this list of conditions and the
-following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the
-following disclaimer in the documentation and/or other
-materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-contributors may be used to endorse or promote products
-derived from this software without specific prior
-written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------------
-*/
-
-/** @file  Win32DebugLogStream.h
-*  @brief Implementation of Win32DebugLogStream
-*/
-#ifndef AI_WIN32DEBUGLOGSTREAM_H_INC
-#define AI_WIN32DEBUGLOGSTREAM_H_INC
-
-#ifdef _WIN32
-
-#include <assimp/LogStream.hpp>
-#include "windows.h"
-
-namespace Assimp    {
-
-// ---------------------------------------------------------------------------
-/** @class  Win32DebugLogStream
- *  @brief  Logs into the debug stream from win32.
- */
-class Win32DebugLogStream : public LogStream {
-public:
-    /** @brief  Default constructor */
-    Win32DebugLogStream();
-
-    /** @brief  Destructor  */
-    ~Win32DebugLogStream();
-
-    /** @brief  Writer  */
-    void write(const char* messgae);
-};
-
-// ---------------------------------------------------------------------------
-inline 
-Win32DebugLogStream::Win32DebugLogStream(){ 
-    // empty
-}
-
-// ---------------------------------------------------------------------------
-inline 
-Win32DebugLogStream::~Win32DebugLogStream(){
-    // empty
-}
-
-// ---------------------------------------------------------------------------
-inline 
-void Win32DebugLogStream::write(const char* message) {
-    ::OutputDebugStringA( message);
-}
-
-// ---------------------------------------------------------------------------
-}   // Namespace Assimp
-
-#endif // ! _WIN32
-#endif // guard

+ 0 - 196
thirdparty/assimp/code/Common/assbin_chunks.h

@@ -1,196 +0,0 @@
-#ifndef INCLUDED_ASSBIN_CHUNKS_H
-#define INCLUDED_ASSBIN_CHUNKS_H
-
-#define ASSBIN_VERSION_MAJOR 1
-#define ASSBIN_VERSION_MINOR 0
-
-/**
-@page assfile .ASS File formats
-
-@section over Overview
-Assimp provides its own interchange format, which is intended to applications which need
-to serialize 3D-models and to reload them quickly. Assimp's file formats are designed to
-be read by Assimp itself. They encode additional information needed by Assimp to optimize
-its postprocessing pipeline. If you once apply specific steps to a scene, then save it
-and reread it from an ASS format using the same post processing settings, they won't
-be executed again.
-
-The format comes in two flavours: XML and binary - both of them hold a complete dump of
-the 'aiScene' data structure returned by the APIs. The focus for the binary format
-(<tt>.assbin</tt>) is fast loading. Optional deflate compression helps reduce file size. The XML
-flavour, <tt>.assxml</tt> or simply .xml, is just a plain-to-xml conversion of aiScene.
-
-ASSBIN is Assimp's binary interchange format. assimp_cmd (<tt>&lt;root&gt;/tools/assimp_cmd</tt>) is able to
-write it and the core library provides a loader for it.
-
-@section assxml XML File format
-
-The format is pretty much self-explanatory due to its similarity to the in-memory aiScene structure.
-With few exceptions, C structures are wrapped in XML elements.
-
-The DTD for ASSXML can be found in <tt>&lt;root&gt;/doc/AssXML_Scheme.xml</tt>. Or have   look
-at the output files generated by assimp_cmd.
-
-@section assbin Binary file format
-
-The ASSBIN file format is composed of chunks to represent the hierarchical aiScene data structure.
-This makes the format extensible and allows backward-compatibility with future data structure
-versions. The <tt>&lt;root&gt;/code/assbin_chunks.h</tt> header contains some magic constants
-for use by stand-alone ASSBIN loaders. Also, Assimp's own file writer can be found
-in <tt>&lt;root&gt;/tools/assimp_cmd/WriteDumb.cpp</tt> (yes, the 'b' is no typo ...).
-
-@verbatim
-
--------------------------------------------------------------------------------
-1. File structure:
--------------------------------------------------------------------------------
-
-----------------------
-| Header (512 bytes) |
-----------------------
-| Variable chunks    |
-----------------------
-
--------------------------------------------------------------------------------
-2. Definitions:
--------------------------------------------------------------------------------
-
-integer is four bytes wide, stored in little-endian byte order.
-short   is two bytes wide, stored in little-endian byte order.
-byte    is a single byte.
-string  is an integer n followed by n UTF-8 characters, not terminated by zero
-float   is an IEEE 754 single-precision floating-point value
-double  is an IEEE 754 double-precision floating-point value
-t[n]    is an array of n elements of type t
-
--------------------------------------------------------------------------------
-2. Header:
--------------------------------------------------------------------------------
-
-byte[44]    Magic identification string for ASSBIN files.
-                'ASSIMP.binary'
-
-integer     Major version of the Assimp library which wrote the file
-integer     Minor version of the Assimp library which wrote the file
-                match these against ASSBIN_VERSION_MAJOR and ASSBIN_VERSION_MINOR
-
-integer     SVN revision of the Assimp library (intended for our internal
-            debugging - if you write Ass files from your own APPs, set this value to 0.
-integer     Assimp compile flags
-
-short       0 for normal files, 1 for shortened dumps for regression tests
-                these should have the file extension assbin.regress
-
-short       1 if the data after the header is compressed with the DEFLATE algorithm,
-            0 for uncompressed files.
-                   For compressed files, the first integer after the header is
-                   always the uncompressed data size
-
-byte[256]   Zero-terminated source file name, UTF-8
-byte[128]   Zero-terminated command line parameters passed to assimp_cmd, UTF-8
-
-byte[64]    Reserved for future use
----> Total length: 512 bytes
-
--------------------------------------------------------------------------------
-3. Chunks:
--------------------------------------------------------------------------------
-
-integer     Magic chunk ID (ASSBIN_CHUNK_XXX)
-integer     Chunk data length, in bytes
-                (unknown chunks are possible, a good reader skips over them)
-                (chunk-data-length does not include the first two integers)
-
-byte[n]     chunk-data-length bytes of data, depending on the chunk type
-
-Chunks can contain nested chunks. Nested chunks are ALWAYS at the end of the chunk,
-their size is included in chunk-data-length.
-
-The chunk layout for all ASSIMP data structures is derived from their C declarations.
-The general 'rule' to get from Assimp headers to the serialized layout is:
-
-   1. POD members (i.e. aiMesh::mPrimitiveTypes, aiMesh::mNumVertices),
-        in order of declaration.
-
-   2. Array-members (aiMesh::mFaces, aiMesh::mVertices, aiBone::mWeights),
-        in order of declaration.
-
-   2. Object array members (i.e aiMesh::mBones, aiScene::mMeshes) are stored in
-      subchunks directly following the data written in 1.) and 2.)
-
-
-    Of course, there are some exceptions to this general order:
-
-[[aiScene]]
-
-   - The root node holding the scene structure is naturally stored in
-     a ASSBIN_CHUNK_AINODE subchunk following 1.) and 2.) (which is
-     empty for aiScene).
-
-[[aiMesh]]
-
-   - mTextureCoords and mNumUVComponents are serialized as follows:
-
-   [number of used uv channels times]
-       integer mNumUVComponents[n]
-       float mTextureCoords[n][3]
-
-       -> more than AI_MAX_TEXCOORD_CHANNELS can be stored. This allows Assimp
-       builds with different settings for AI_MAX_TEXCOORD_CHANNELS to exchange
-       data.
-       -> the on-disk format always uses 3 floats to write UV coordinates.
-       If mNumUVComponents[0] is 1, the corresponding mTextureCoords array
-       consists of 3 floats.
-
-   - The array member block of aiMesh is prefixed with an integer that specifies
-     the kinds of vertex components actually present in the mesh. This is a
-     bitwise combination of the ASSBIN_MESH_HAS_xxx constants.
-
-[[aiFace]]
-
-   - mNumIndices is stored as short
-   - mIndices are written as short, if aiMesh::mNumVertices<65536
-
-[[aiNode]]
-
-   - mParent is omitted
-
-[[aiLight]]
-
-   - mAttenuationXXX not written if aiLight::mType == aiLightSource_DIRECTIONAL
-   - mAngleXXX not written if aiLight::mType != aiLightSource_SPOT
-
-[[aiMaterial]]
-
-   - mNumAllocated is omitted, for obvious reasons :-)
-
-
- @endverbatim*/
-
-
-#define ASSBIN_HEADER_LENGTH 512
-
-// these are the magic chunk identifiers for the binary ASS file format
-#define ASSBIN_CHUNK_AICAMERA                   0x1234
-#define ASSBIN_CHUNK_AILIGHT                    0x1235
-#define ASSBIN_CHUNK_AITEXTURE                  0x1236
-#define ASSBIN_CHUNK_AIMESH                     0x1237
-#define ASSBIN_CHUNK_AINODEANIM                 0x1238
-#define ASSBIN_CHUNK_AISCENE                    0x1239
-#define ASSBIN_CHUNK_AIBONE                     0x123a
-#define ASSBIN_CHUNK_AIANIMATION                0x123b
-#define ASSBIN_CHUNK_AINODE                     0x123c
-#define ASSBIN_CHUNK_AIMATERIAL                 0x123d
-#define ASSBIN_CHUNK_AIMATERIALPROPERTY         0x123e
-
-#define ASSBIN_MESH_HAS_POSITIONS                   0x1
-#define ASSBIN_MESH_HAS_NORMALS                     0x2
-#define ASSBIN_MESH_HAS_TANGENTS_AND_BITANGENTS     0x4
-#define ASSBIN_MESH_HAS_TEXCOORD_BASE               0x100
-#define ASSBIN_MESH_HAS_COLOR_BASE                  0x10000
-
-#define ASSBIN_MESH_HAS_TEXCOORD(n) (ASSBIN_MESH_HAS_TEXCOORD_BASE << n)
-#define ASSBIN_MESH_HAS_COLOR(n)    (ASSBIN_MESH_HAS_COLOR_BASE << n)
-
-
-#endif // INCLUDED_ASSBIN_CHUNKS_H

+ 0 - 140
thirdparty/assimp/code/Common/scene.cpp

@@ -1,140 +0,0 @@
-/*
----------------------------------------------------------------------------
-Open Asset Import Library (assimp)
----------------------------------------------------------------------------
-
-Copyright (c) 2006-2019, 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 <assimp/scene.h>
-
-aiNode::aiNode()
-: mName("")
-, mParent(nullptr)
-, mNumChildren(0)
-, mChildren(nullptr)
-, mNumMeshes(0)
-, mMeshes(nullptr)
-, mMetaData(nullptr) {
-    // empty
-}
-
-aiNode::aiNode(const std::string& name)
-: mName(name)
-, mParent(nullptr)
-, mNumChildren(0)
-, mChildren(nullptr)
-, mNumMeshes(0)
-, mMeshes(nullptr)
-, mMetaData(nullptr) {
-    // empty
-}
-
-/** Destructor */
-aiNode::~aiNode() {
-    // delete all children recursively
-    // to make sure we won't crash if the data is invalid ...
-    if (mNumChildren && mChildren)
-    {
-        for (unsigned int a = 0; a < mNumChildren; a++)
-            delete mChildren[a];
-    }
-    delete[] mChildren;
-    delete[] mMeshes;
-    delete mMetaData;
-}
-
-const aiNode *aiNode::FindNode(const char* name) const {
-    if (nullptr == name) {
-        return nullptr;
-    }
-    if (!::strcmp(mName.data, name)) {
-        return this;
-    }
-    for (unsigned int i = 0; i < mNumChildren; ++i) {
-        const aiNode* const p = mChildren[i]->FindNode(name);
-        if (p) {
-            return p;
-        }
-    }
-    // there is definitely no sub-node with this name
-    return nullptr;
-}
-
-aiNode *aiNode::FindNode(const char* name) {
-    if (!::strcmp(mName.data, name))return this;
-    for (unsigned int i = 0; i < mNumChildren; ++i)
-    {
-        aiNode* const p = mChildren[i]->FindNode(name);
-        if (p) {
-            return p;
-        }
-    }
-    // there is definitely no sub-node with this name
-    return nullptr;
-}
-
-void aiNode::addChildren(unsigned int numChildren, aiNode **children) {
-    if (nullptr == children || 0 == numChildren) {
-        return;
-    }
-
-    for (unsigned int i = 0; i < numChildren; i++) {
-        aiNode *child = children[i];
-        if (nullptr != child) {
-            child->mParent = this;
-        }
-    }
-
-    if (mNumChildren > 0) {
-        aiNode **tmp = new aiNode*[mNumChildren];
-        ::memcpy(tmp, mChildren, sizeof(aiNode*) * mNumChildren);
-        delete[] mChildren;
-        mChildren = new aiNode*[mNumChildren + numChildren];
-        ::memcpy(mChildren, tmp, sizeof(aiNode*) * mNumChildren);
-        ::memcpy(&mChildren[mNumChildren], children, sizeof(aiNode*)* numChildren);
-        mNumChildren += numChildren;
-        delete[] tmp;
-    }
-    else {
-        mChildren = new aiNode*[numChildren];
-        for (unsigned int i = 0; i < numChildren; i++) {
-            mChildren[i] = children[i];
-        }
-        mNumChildren = numChildren;
-    }
-}

+ 0 - 79
thirdparty/assimp/code/Common/simd.cpp

@@ -1,79 +0,0 @@
-/*
----------------------------------------------------------------------------
-Open Asset Import Library (assimp)
----------------------------------------------------------------------------
-
-Copyright (c) 2006-2019, 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 "simd.h"
-
-namespace Assimp {
-
-bool CPUSupportsSSE2() {
-#if defined(__x86_64__) || defined(_M_X64)
-    //* x86_64 always has SSE2 instructions */
-    return true;
-#elif defined(__GNUC__) && defined(i386)
-    // for GCC x86 we check cpuid
-    unsigned int d;
-    __asm__(
-        "pushl %%ebx\n\t"
-        "cpuid\n\t"
-        "popl %%ebx\n\t"
-        : "=d" ( d )
-        :"a" ( 1 ) );
-    return ( d & 0x04000000 ) != 0;
-#elif (defined(_MSC_VER) && defined(_M_IX86))
-    // also check cpuid for MSVC x86
-    unsigned int d;
-    __asm {
-        xor     eax, eax
-        inc eax
-        push ebx
-        cpuid
-        pop ebx
-        mov d, edx
-    }
-    return ( d & 0x04000000 ) != 0;
-#else
-    return false;
-#endif
-}
-
-
-} // Namespace Assimp

+ 0 - 53
thirdparty/assimp/code/Common/simd.h

@@ -1,53 +0,0 @@
-/*
----------------------------------------------------------------------------
-Open Asset Import Library (assimp)
----------------------------------------------------------------------------
-
-Copyright (c) 2006-2019, 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.
----------------------------------------------------------------------------
-*/
-#pragma once
-
-#include <assimp/defs.h>
-
-namespace Assimp {
-
-/// @brief  Checks if the platform supports SSE2 optimization
-/// @return true, if SSE2 is supported. false if SSE2 is not supported.
-bool ASSIMP_API CPUSupportsSSE2();
-
-} // Namespace Assimp

+ 0 - 305
thirdparty/assimp/code/FBX/FBXAnimation.cpp

@@ -1,305 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file  FBXAnimation.cpp
- *  @brief Assimp::FBX::AnimationCurve, Assimp::FBX::AnimationCurveNode,
- *         Assimp::FBX::AnimationLayer, Assimp::FBX::AnimationStack
- */
-
-#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
-
-#include "FBXParser.h"
-#include "FBXDocument.h"
-#include "FBXImporter.h"
-#include "FBXDocumentUtil.h"
-
-namespace Assimp {
-namespace FBX {
-
-using namespace Util;
-
-// ------------------------------------------------------------------------------------------------
-AnimationCurve::AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& /*doc*/)
-: Object(id, element, name)
-{
-    const Scope& sc = GetRequiredScope(element);
-    const Element& KeyTime = GetRequiredElement(sc,"KeyTime");
-    const Element& KeyValueFloat = GetRequiredElement(sc,"KeyValueFloat");
-
-    ParseVectorDataArray(keys, KeyTime);
-    ParseVectorDataArray(values, KeyValueFloat);
-
-    if(keys.size() != values.size()) {
-        DOMError("the number of key times does not match the number of keyframe values",&KeyTime);
-    }
-
-    // check if the key times are well-ordered
-    if(!std::equal(keys.begin(), keys.end() - 1, keys.begin() + 1, std::less<KeyTimeList::value_type>())) {
-        DOMError("the keyframes are not in ascending order",&KeyTime);
-    }
-
-    const Element* KeyAttrDataFloat = sc["KeyAttrDataFloat"];
-    if(KeyAttrDataFloat) {
-        ParseVectorDataArray(attributes, *KeyAttrDataFloat);
-    }
-
-    const Element* KeyAttrFlags = sc["KeyAttrFlags"];
-    if(KeyAttrFlags) {
-        ParseVectorDataArray(flags, *KeyAttrFlags);
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-AnimationCurve::~AnimationCurve()
-{
-    // empty
-}
-
-// ------------------------------------------------------------------------------------------------
-AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, 
-        const Document& doc, const char* const * target_prop_whitelist /*= NULL*/, 
-        size_t whitelist_size /*= 0*/)
-: Object(id, element, name)
-, target()
-, doc(doc)
-{
-    const Scope& sc = GetRequiredScope(element);
-
-    // find target node
-    const char* whitelist[] = {"Model","NodeAttribute","Deformer"};
-    const std::vector<const Connection*>& conns = doc.GetConnectionsBySourceSequenced(ID(),whitelist,3);
-
-    for(const Connection* con : conns) {
-
-        // link should go for a property
-        if (!con->PropertyName().length()) {
-            continue;
-        }
-
-        if(target_prop_whitelist) {
-            const char* const s = con->PropertyName().c_str();
-            bool ok = false;
-            for (size_t i = 0; i < whitelist_size; ++i) {
-                if (!strcmp(s, target_prop_whitelist[i])) {
-                    ok = true;
-                    break;
-                }
-            }
-
-            if (!ok) {
-                throw std::range_error("AnimationCurveNode target property is not in whitelist");
-            }
-        }
-
-        const Object* const ob = con->DestinationObject();
-        if(!ob) {
-            DOMWarning("failed to read destination object for AnimationCurveNode->Model link, ignoring",&element);
-            continue;
-        }
-
-        // XXX support constraints as DOM class
-        //ai_assert(dynamic_cast<const Model*>(ob) || dynamic_cast<const NodeAttribute*>(ob));
-        target = ob;
-        if(!target) {
-            continue;
-        }
-
-        prop = con->PropertyName();
-        break;
-    }
-
-    if(!target) {
-        DOMWarning("failed to resolve target Model/NodeAttribute/Constraint for AnimationCurveNode",&element);
-    }
-
-    props = GetPropertyTable(doc,"AnimationCurveNode.FbxAnimCurveNode",element,sc,false);
-}
-
-// ------------------------------------------------------------------------------------------------
-AnimationCurveNode::~AnimationCurveNode()
-{
-    // empty
-}
-
-// ------------------------------------------------------------------------------------------------
-const AnimationCurveMap& AnimationCurveNode::Curves() const
-{
-    if ( curves.empty() ) {
-        // resolve attached animation curves
-        const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationCurve");
-
-        for(const Connection* con : conns) {
-
-            // link should go for a property
-            if (!con->PropertyName().length()) {
-                continue;
-            }
-
-            const Object* const ob = con->SourceObject();
-            if(!ob) {
-                DOMWarning("failed to read source object for AnimationCurve->AnimationCurveNode link, ignoring",&element);
-                continue;
-            }
-
-            const AnimationCurve* const anim = dynamic_cast<const AnimationCurve*>(ob);
-            if(!anim) {
-                DOMWarning("source object for ->AnimationCurveNode link is not an AnimationCurve",&element);
-                continue;
-            }
-
-            curves[con->PropertyName()] = anim;
-        }
-    }
-
-    return curves;
-}
-
-// ------------------------------------------------------------------------------------------------
-AnimationLayer::AnimationLayer(uint64_t id, const Element& element, const std::string& name, const Document& doc)
-: Object(id, element, name)
-, doc(doc)
-{
-    const Scope& sc = GetRequiredScope(element);
-
-    // note: the props table here bears little importance and is usually absent
-    props = GetPropertyTable(doc,"AnimationLayer.FbxAnimLayer",element,sc, true);
-}
-
-// ------------------------------------------------------------------------------------------------
-AnimationLayer::~AnimationLayer()
-{
-    // empty
-}
-
-// ------------------------------------------------------------------------------------------------
-AnimationCurveNodeList AnimationLayer::Nodes(const char* const * target_prop_whitelist /*= NULL*/,
-    size_t whitelist_size /*= 0*/) const
-{
-    AnimationCurveNodeList nodes;
-
-    // resolve attached animation nodes
-    const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationCurveNode");
-    nodes.reserve(conns.size());
-
-    for(const Connection* con : conns) {
-
-        // link should not go to a property
-        if (con->PropertyName().length()) {
-            continue;
-        }
-
-        const Object* const ob = con->SourceObject();
-        if(!ob) {
-            DOMWarning("failed to read source object for AnimationCurveNode->AnimationLayer link, ignoring",&element);
-            continue;
-        }
-
-        const AnimationCurveNode* const anim = dynamic_cast<const AnimationCurveNode*>(ob);
-        if(!anim) {
-            DOMWarning("source object for ->AnimationLayer link is not an AnimationCurveNode",&element);
-            continue;
-        }
-
-        if(target_prop_whitelist) {
-            const char* s = anim->TargetProperty().c_str();
-            bool ok = false;
-            for (size_t i = 0; i < whitelist_size; ++i) {
-                if (!strcmp(s, target_prop_whitelist[i])) {
-                    ok = true;
-                    break;
-                }
-            }
-            if(!ok) {
-                continue;
-            }
-        }
-        nodes.push_back(anim);
-    }
-
-    return nodes; // pray for NRVO
-}
-
-// ------------------------------------------------------------------------------------------------
-AnimationStack::AnimationStack(uint64_t id, const Element& element, const std::string& name, const Document& doc)
-: Object(id, element, name)
-{
-    const Scope& sc = GetRequiredScope(element);
-
-    // note: we don't currently use any of these properties so we shouldn't bother if it is missing
-    props = GetPropertyTable(doc,"AnimationStack.FbxAnimStack",element,sc, true);
-
-    // resolve attached animation layers
-    const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationLayer");
-    layers.reserve(conns.size());
-
-    for(const Connection* con : conns) {
-
-        // link should not go to a property
-        if (con->PropertyName().length()) {
-            continue;
-        }
-
-        const Object* const ob = con->SourceObject();
-        if(!ob) {
-            DOMWarning("failed to read source object for AnimationLayer->AnimationStack link, ignoring",&element);
-            continue;
-        }
-
-        const AnimationLayer* const anim = dynamic_cast<const AnimationLayer*>(ob);
-        if(!anim) {
-            DOMWarning("source object for ->AnimationStack link is not an AnimationLayer",&element);
-            continue;
-        }
-        layers.push_back(anim);
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-AnimationStack::~AnimationStack()
-{
-    // empty
-}
-
-} //!FBX
-} //!Assimp
-
-#endif // ASSIMP_BUILD_NO_FBX_IMPORTER

+ 0 - 466
thirdparty/assimp/code/FBX/FBXBinaryTokenizer.cpp

@@ -1,466 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-/** @file  FBXBinaryTokenizer.cpp
- *  @brief Implementation of a fake lexer for binary fbx files -
- *    we emit tokens so the parser needs almost no special handling
- *    for binary files.
- */
-
-#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
-
-#include "FBXTokenizer.h"
-#include "FBXUtil.h"
-#include <assimp/defs.h>
-#include <stdint.h>
-#include <assimp/Exceptional.h>
-#include <assimp/ByteSwapper.h>
-
-namespace Assimp {
-namespace FBX {
-
-//enum Flag
-//{
-//   e_unknown_0 = 1 << 0,
-//   e_unknown_1 = 1 << 1,
-//   e_unknown_2 = 1 << 2,
-//   e_unknown_3 = 1 << 3,
-//   e_unknown_4 = 1 << 4,
-//   e_unknown_5 = 1 << 5,
-//   e_unknown_6 = 1 << 6,
-//   e_unknown_7 = 1 << 7,
-//   e_unknown_8 = 1 << 8,
-//   e_unknown_9 = 1 << 9,
-//   e_unknown_10 = 1 << 10,
-//   e_unknown_11 = 1 << 11,
-//   e_unknown_12 = 1 << 12,
-//   e_unknown_13 = 1 << 13,
-//   e_unknown_14 = 1 << 14,
-//   e_unknown_15 = 1 << 15,
-//   e_unknown_16 = 1 << 16,
-//   e_unknown_17 = 1 << 17,
-//   e_unknown_18 = 1 << 18,
-//   e_unknown_19 = 1 << 19,
-//   e_unknown_20 = 1 << 20,
-//   e_unknown_21 = 1 << 21,
-//   e_unknown_22 = 1 << 22,
-//   e_unknown_23 = 1 << 23,
-//   e_flag_field_size_64_bit = 1 << 24, // Not sure what is
-//   e_unknown_25 = 1 << 25,
-//   e_unknown_26 = 1 << 26,
-//   e_unknown_27 = 1 << 27,
-//   e_unknown_28 = 1 << 28,
-//   e_unknown_29 = 1 << 29,
-//   e_unknown_30 = 1 << 30,
-//   e_unknown_31 = 1 << 31
-//};
-//
-//bool check_flag(uint32_t flags, Flag to_check)
-//{
-//	return (flags & to_check) != 0;
-//}
-// ------------------------------------------------------------------------------------------------
-Token::Token(const char* sbegin, const char* send, TokenType type, size_t offset)
-    :
-    #ifdef DEBUG
-    contents(sbegin, static_cast<size_t>(send-sbegin)),
-    #endif
-    sbegin(sbegin)
-    , send(send)
-    , type(type)
-    , line(offset)
-    , column(BINARY_MARKER)
-{
-    ai_assert(sbegin);
-    ai_assert(send);
-
-    // binary tokens may have zero length because they are sometimes dummies
-    // inserted by TokenizeBinary()
-    ai_assert(send >= sbegin);
-}
-
-
-namespace {
-
-// ------------------------------------------------------------------------------------------------
-// signal tokenization error, this is always unrecoverable. Throws DeadlyImportError.
-AI_WONT_RETURN void TokenizeError(const std::string& message, size_t offset) AI_WONT_RETURN_SUFFIX;
-AI_WONT_RETURN void TokenizeError(const std::string& message, size_t offset)
-{
-    throw DeadlyImportError(Util::AddOffset("FBX-Tokenize",message,offset));
-}
-
-
-// ------------------------------------------------------------------------------------------------
-size_t Offset(const char* begin, const char* cursor) {
-    ai_assert(begin <= cursor);
-
-    return cursor - begin;
-}
-
-// ------------------------------------------------------------------------------------------------
-void TokenizeError(const std::string& message, const char* begin, const char* cursor) {
-    TokenizeError(message, Offset(begin, cursor));
-}
-
-// ------------------------------------------------------------------------------------------------
-uint32_t ReadWord(const char* input, const char*& cursor, const char* end) {
-    const size_t k_to_read = sizeof( uint32_t );
-    if(Offset(cursor, end) < k_to_read ) {
-        TokenizeError("cannot ReadWord, out of bounds",input, cursor);
-    }
-
-    uint32_t word;
-    ::memcpy(&word, cursor, 4);
-    AI_SWAP4(word);
-
-    cursor += k_to_read;
-
-    return word;
-}
-
-// ------------------------------------------------------------------------------------------------
-uint64_t ReadDoubleWord(const char* input, const char*& cursor, const char* end) {
-    const size_t k_to_read = sizeof(uint64_t);
-    if(Offset(cursor, end) < k_to_read) {
-        TokenizeError("cannot ReadDoubleWord, out of bounds",input, cursor);
-    }
-
-    uint64_t dword /*= *reinterpret_cast<const uint64_t*>(cursor)*/;
-    ::memcpy( &dword, cursor, sizeof( uint64_t ) );
-    AI_SWAP8(dword);
-
-    cursor += k_to_read;
-
-    return dword;
-}
-
-// ------------------------------------------------------------------------------------------------
-uint8_t ReadByte(const char* input, const char*& cursor, const char* end) {
-    if(Offset(cursor, end) < sizeof( uint8_t ) ) {
-        TokenizeError("cannot ReadByte, out of bounds",input, cursor);
-    }
-
-    uint8_t word;/* = *reinterpret_cast< const uint8_t* >( cursor )*/
-    ::memcpy( &word, cursor, sizeof( uint8_t ) );
-    ++cursor;
-
-    return word;
-}
-
-// ------------------------------------------------------------------------------------------------
-unsigned int ReadString(const char*& sbegin_out, const char*& send_out, const char* input,
-        const char*& cursor, const char* end, bool long_length = false, bool allow_null = false) {
-    const uint32_t len_len = long_length ? 4 : 1;
-    if(Offset(cursor, end) < len_len) {
-        TokenizeError("cannot ReadString, out of bounds reading length",input, cursor);
-    }
-
-    const uint32_t length = long_length ? ReadWord(input, cursor, end) : ReadByte(input, cursor, end);
-
-    if (Offset(cursor, end) < length) {
-        TokenizeError("cannot ReadString, length is out of bounds",input, cursor);
-    }
-
-    sbegin_out = cursor;
-    cursor += length;
-
-    send_out = cursor;
-
-    if(!allow_null) {
-        for (unsigned int i = 0; i < length; ++i) {
-            if(sbegin_out[i] == '\0') {
-                TokenizeError("failed ReadString, unexpected NUL character in string",input, cursor);
-            }
-        }
-    }
-
-    return length;
-}
-
-// ------------------------------------------------------------------------------------------------
-void ReadData(const char*& sbegin_out, const char*& send_out, const char* input, const char*& cursor, const char* end) {
-    if(Offset(cursor, end) < 1) {
-        TokenizeError("cannot ReadData, out of bounds reading length",input, cursor);
-    }
-
-    const char type = *cursor;
-    sbegin_out = cursor++;
-
-    switch(type)
-    {
-        // 16 bit int
-    case 'Y':
-        cursor += 2;
-        break;
-
-        // 1 bit bool flag (yes/no)
-    case 'C':
-        cursor += 1;
-        break;
-
-        // 32 bit int
-    case 'I':
-        // <- fall through
-
-        // float
-    case 'F':
-        cursor += 4;
-        break;
-
-        // double
-    case 'D':
-        cursor += 8;
-        break;
-
-        // 64 bit int
-    case 'L':
-        cursor += 8;
-        break;
-
-        // note: do not write cursor += ReadWord(...cursor) as this would be UB
-
-        // raw binary data
-    case 'R':
-    {
-        const uint32_t length = ReadWord(input, cursor, end);
-        cursor += length;
-        break;
-    }
-
-    case 'b':
-        // TODO: what is the 'b' type code? Right now we just skip over it /
-        // take the full range we could get
-        cursor = end;
-        break;
-
-        // array of *
-    case 'f':
-    case 'd':
-    case 'l':
-    case 'i':
-    case 'c':   {
-        const uint32_t length = ReadWord(input, cursor, end);
-        const uint32_t encoding = ReadWord(input, cursor, end);
-
-        const uint32_t comp_len = ReadWord(input, cursor, end);
-
-        // compute length based on type and check against the stored value
-        if(encoding == 0) {
-            uint32_t stride = 0;
-            switch(type)
-            {
-            case 'f':
-            case 'i':
-                stride = 4;
-                break;
-
-            case 'd':
-            case 'l':
-                stride = 8;
-                break;
-
-            case 'c':
-                stride = 1;
-                break;
-
-            default:
-                ai_assert(false);
-            };
-            ai_assert(stride > 0);
-            if(length * stride != comp_len) {
-                TokenizeError("cannot ReadData, calculated data stride differs from what the file claims",input, cursor);
-            }
-        }
-        // zip/deflate algorithm (encoding==1)? take given length. anything else? die
-        else if (encoding != 1) {
-            TokenizeError("cannot ReadData, unknown encoding",input, cursor);
-        }
-        cursor += comp_len;
-        break;
-    }
-
-        // string
-    case 'S': {
-        const char* sb, *se;
-        // 0 characters can legally happen in such strings
-        ReadString(sb, se, input, cursor, end, true, true);
-        break;
-    }
-    default:
-        TokenizeError("cannot ReadData, unexpected type code: " + std::string(&type, 1),input, cursor);
-    }
-
-    if(cursor > end) {
-        TokenizeError("cannot ReadData, the remaining size is too small for the data type: " + std::string(&type, 1),input, cursor);
-    }
-
-    // the type code is contained in the returned range
-    send_out = cursor;
-}
-
-
-// ------------------------------------------------------------------------------------------------
-bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor, const char* end, bool const is64bits)
-{
-    // the first word contains the offset at which this block ends
-	const uint64_t end_offset = is64bits ? ReadDoubleWord(input, cursor, end) : ReadWord(input, cursor, end);
-
-    // we may get 0 if reading reached the end of the file -
-    // fbx files have a mysterious extra footer which I don't know
-    // how to extract any information from, but at least it always
-    // starts with a 0.
-    if(!end_offset) {
-        return false;
-    }
-
-    if(end_offset > Offset(input, end)) {
-        TokenizeError("block offset is out of range",input, cursor);
-    }
-    else if(end_offset < Offset(input, cursor)) {
-        TokenizeError("block offset is negative out of range",input, cursor);
-    }
-
-    // the second data word contains the number of properties in the scope
-	const uint64_t prop_count = is64bits ? ReadDoubleWord(input, cursor, end) : ReadWord(input, cursor, end);
-
-    // the third data word contains the length of the property list
-	const uint64_t prop_length = is64bits ? ReadDoubleWord(input, cursor, end) : ReadWord(input, cursor, end);
-
-    // now comes the name of the scope/key
-    const char* sbeg, *send;
-    ReadString(sbeg, send, input, cursor, end);
-
-    output_tokens.push_back(new_Token(sbeg, send, TokenType_KEY, Offset(input, cursor) ));
-
-    // now come the individual properties
-    const char* begin_cursor = cursor;
-    for (unsigned int i = 0; i < prop_count; ++i) {
-        ReadData(sbeg, send, input, cursor, begin_cursor + prop_length);
-
-        output_tokens.push_back(new_Token(sbeg, send, TokenType_DATA, Offset(input, cursor) ));
-
-        if(i != prop_count-1) {
-            output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_COMMA, Offset(input, cursor) ));
-        }
-    }
-
-    if (Offset(begin_cursor, cursor) != prop_length) {
-        TokenizeError("property length not reached, something is wrong",input, cursor);
-    }
-
-    // at the end of each nested block, there is a NUL record to indicate
-    // that the sub-scope exists (i.e. to distinguish between P: and P : {})
-    // this NUL record is 13 bytes long on 32 bit version and 25 bytes long on 64 bit.
-	const size_t sentinel_block_length = is64bits ? (sizeof(uint64_t)* 3 + 1) : (sizeof(uint32_t)* 3 + 1);
-
-    if (Offset(input, cursor) < end_offset) {
-        if (end_offset - Offset(input, cursor) < sentinel_block_length) {
-            TokenizeError("insufficient padding bytes at block end",input, cursor);
-        }
-
-        output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_OPEN_BRACKET, Offset(input, cursor) ));
-
-        // XXX this is vulnerable to stack overflowing ..
-        while(Offset(input, cursor) < end_offset - sentinel_block_length) {
-			ReadScope(output_tokens, input, cursor, input + end_offset - sentinel_block_length, is64bits);
-        }
-        output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_CLOSE_BRACKET, Offset(input, cursor) ));
-
-        for (unsigned int i = 0; i < sentinel_block_length; ++i) {
-            if(cursor[i] != '\0') {
-                TokenizeError("failed to read nested block sentinel, expected all bytes to be 0",input, cursor);
-            }
-        }
-        cursor += sentinel_block_length;
-    }
-
-    if (Offset(input, cursor) != end_offset) {
-        TokenizeError("scope length not reached, something is wrong",input, cursor);
-    }
-
-    return true;
-}
-
-} // anonymous namespace
-
-// ------------------------------------------------------------------------------------------------
-// TODO: Test FBX Binary files newer than the 7500 version to check if the 64 bits address behaviour is consistent
-void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length)
-{
-    ai_assert(input);
-
-    if(length < 0x1b) {
-        TokenizeError("file is too short",0);
-    }
-
-    //uint32_t offset = 0x15;
-/*    const char* cursor = input + 0x15;
-
-    const uint32_t flags = ReadWord(input, cursor, input + length);
-
-    const uint8_t padding_0 = ReadByte(input, cursor, input + length); // unused
-    const uint8_t padding_1 = ReadByte(input, cursor, input + length); // unused*/
-
-    if (strncmp(input,"Kaydara FBX Binary",18)) {
-        TokenizeError("magic bytes not found",0);
-    }
-
-    const char* cursor = input + 18;
-	/*Result ignored*/ ReadByte(input, cursor, input + length);
-	/*Result ignored*/ ReadByte(input, cursor, input + length);
-	/*Result ignored*/ ReadByte(input, cursor, input + length);
-	/*Result ignored*/ ReadByte(input, cursor, input + length);
-	/*Result ignored*/ ReadByte(input, cursor, input + length);
-	const uint32_t version = ReadWord(input, cursor, input + length);
-	const bool is64bits = version >= 7500;
-    const char *end = input + length;
-    while (cursor < end ) {
-		if (!ReadScope(output_tokens, input, cursor, input + length, is64bits)) {
-            break;
-        }
-    }
-}
-
-} // !FBX
-} // !Assimp
-
-#endif

+ 0 - 86
thirdparty/assimp/code/FBX/FBXCommon.h

@@ -1,86 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-copyright notice, this list of conditions and the
-following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the
-following disclaimer in the documentation and/or other
-materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-contributors may be used to endorse or promote products
-derived from this software without specific prior
-written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file FBXCommon.h
-* Some useful constants and enums for dealing with FBX files.
-*/
-#ifndef AI_FBXCOMMON_H_INC
-#define AI_FBXCOMMON_H_INC
-
-#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
-
-namespace Assimp {
-namespace FBX
-{
-    const std::string NULL_RECORD = { // 13 null bytes
-        '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0'
-    }; // who knows why
-    const std::string SEPARATOR = {'\x00', '\x01'}; // for use inside strings
-    const std::string MAGIC_NODE_TAG = "_$AssimpFbx$"; // from import
-    const int64_t SECOND = 46186158000; // FBX's kTime unit
-
-    // rotation order. We'll probably use EulerXYZ for everything
-    enum RotOrder {
-        RotOrder_EulerXYZ = 0,
-        RotOrder_EulerXZY,
-        RotOrder_EulerYZX,
-        RotOrder_EulerYXZ,
-        RotOrder_EulerZXY,
-        RotOrder_EulerZYX,
-
-        RotOrder_SphericXYZ,
-
-        RotOrder_MAX // end-of-enum sentinel
-    };
-
-    // transformation inheritance method. Most of the time RSrs
-    enum TransformInheritance {
-        TransformInheritance_RrSs = 0,
-        TransformInheritance_RSrs,
-        TransformInheritance_Rrs,
-
-        TransformInheritance_MAX // end-of-enum sentinel
-    };
-}
-}
-#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
-
-#endif // AI_FBXCOMMON_H_INC

+ 0 - 78
thirdparty/assimp/code/FBX/FBXCompileConfig.h

@@ -1,78 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file  FBXCompileConfig.h
- *  @brief FBX importer compile-time switches
- */
-#ifndef INCLUDED_AI_FBX_COMPILECONFIG_H
-#define INCLUDED_AI_FBX_COMPILECONFIG_H
-
-#include <map>
-#include <set>
-
-//
-#if _MSC_VER > 1500 || (defined __GNUC___)
-#   define ASSIMP_FBX_USE_UNORDERED_MULTIMAP
-#   else
-#   define fbx_unordered_map map
-#   define fbx_unordered_multimap multimap
-#   define fbx_unordered_set set
-#   define fbx_unordered_multiset multiset
-#endif
-
-#ifdef ASSIMP_FBX_USE_UNORDERED_MULTIMAP
-#   include <unordered_map>
-#   include <unordered_set>
-#   if _MSC_VER > 1600
-#       define fbx_unordered_map unordered_map
-#       define fbx_unordered_multimap unordered_multimap
-#       define fbx_unordered_set unordered_set
-#       define fbx_unordered_multiset unordered_multiset
-#   else
-#       define fbx_unordered_map tr1::unordered_map
-#       define fbx_unordered_multimap tr1::unordered_multimap
-#       define fbx_unordered_set tr1::unordered_set
-#       define fbx_unordered_multiset tr1::unordered_multiset
-#   endif
-#endif
-
-#endif // INCLUDED_AI_FBX_COMPILECONFIG_H

+ 0 - 3727
thirdparty/assimp/code/FBX/FBXConverter.cpp

@@ -1,3727 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file  FBXConverter.cpp
- *  @brief Implementation of the FBX DOM -> aiScene converter
- */
-
-#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
-
-#include "FBXConverter.h"
-#include "FBXParser.h"
-#include "FBXMeshGeometry.h"
-#include "FBXDocument.h"
-#include "FBXUtil.h"
-#include "FBXProperties.h"
-#include "FBXImporter.h"
-
-#include <assimp/StringComparison.h>
-#include <assimp/MathFunctions.h>
-
-#include <assimp/scene.h>
-
-#include <assimp/CreateAnimMesh.h>
-
-#include <tuple>
-#include <memory>
-#include <iterator>
-#include <vector>
-#include <sstream>
-#include <iomanip>
-#include <cstdint>
-#include <iostream>
-#include <stdlib.h>
-
-namespace Assimp {
-    namespace FBX {
-
-        using namespace Util;
-
-#define MAGIC_NODE_TAG "_$AssimpFbx$"
-
-#define CONVERT_FBX_TIME(time) static_cast<double>(time) / 46186158000LL
-
-        FBXConverter::FBXConverter(aiScene* out, const Document& doc, bool removeEmptyBones )
-        : defaultMaterialIndex()
-        , lights()
-        , cameras()
-        , textures()
-        , materials_converted()
-        , textures_converted()
-        , meshes_converted()
-        , node_anim_chain_bits()
-        , mNodeNames()
-        , anim_fps()
-        , out(out)
-        , doc(doc) {
-            // animations need to be converted first since this will
-            // populate the node_anim_chain_bits map, which is needed
-            // to determine which nodes need to be generated.
-            ConvertAnimations();
-            // Embedded textures in FBX could be connected to nothing but to itself,
-            // for instance Texture -> Video connection only but not to the main graph,
-            // The idea here is to traverse all objects to find these Textures and convert them,
-            // so later during material conversion it will find converted texture in the textures_converted array.
-            if (doc.Settings().readTextures)
-            {
-                ConvertOrphantEmbeddedTextures();
-            }
-            ConvertRootNode();
-
-            if (doc.Settings().readAllMaterials) {
-                // unfortunately this means we have to evaluate all objects
-                for (const ObjectMap::value_type& v : doc.Objects()) {
-
-                    const Object* ob = v.second->Get();
-                    if (!ob) {
-                        continue;
-                    }
-
-                    const Material* mat = dynamic_cast<const Material*>(ob);
-                    if (mat) {
-
-                        if (materials_converted.find(mat) == materials_converted.end()) {
-                            ConvertMaterial(*mat, 0);
-                        }
-                    }
-                }
-            }
-
-            ConvertGlobalSettings();
-            TransferDataToScene();
-
-            // if we didn't read any meshes set the AI_SCENE_FLAGS_INCOMPLETE
-            // to make sure the scene passes assimp's validation. FBX files
-            // need not contain geometry (i.e. camera animations, raw armatures).
-            if (out->mNumMeshes == 0) {
-                out->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
-            }
-        }
-
-
-        FBXConverter::~FBXConverter() {
-            std::for_each(meshes.begin(), meshes.end(), Util::delete_fun<aiMesh>());
-            std::for_each(materials.begin(), materials.end(), Util::delete_fun<aiMaterial>());
-            std::for_each(animations.begin(), animations.end(), Util::delete_fun<aiAnimation>());
-            std::for_each(lights.begin(), lights.end(), Util::delete_fun<aiLight>());
-            std::for_each(cameras.begin(), cameras.end(), Util::delete_fun<aiCamera>());
-            std::for_each(textures.begin(), textures.end(), Util::delete_fun<aiTexture>());
-        }
-
-        void FBXConverter::ConvertRootNode() {
-            out->mRootNode = new aiNode();
-            std::string unique_name;
-            GetUniqueName("RootNode", unique_name);
-            out->mRootNode->mName.Set(unique_name);
-
-            // root has ID 0
-            ConvertNodes(0L, out->mRootNode, out->mRootNode);
-        }
-
-        static std::string getAncestorBaseName(const aiNode* node)
-        {
-            const char* nodeName = nullptr;
-            size_t length = 0;
-            while (node && (!nodeName || length == 0))
-            {
-                nodeName = node->mName.C_Str();
-                length = node->mName.length;
-                node = node->mParent;
-            }
-
-            if (!nodeName || length == 0)
-            {
-                return {};
-            }
-            // could be std::string_view if c++17 available
-            return std::string(nodeName, length);
-        }
-
-        // Make unique name
-        std::string FBXConverter::MakeUniqueNodeName(const Model* const model, const aiNode& parent)
-        {
-            std::string original_name = FixNodeName(model->Name());
-            if (original_name.empty())
-            {
-                original_name = getAncestorBaseName(&parent);
-            }
-            std::string unique_name;
-            GetUniqueName(original_name, unique_name);
-            return unique_name;
-        }
-        /// todo: pre-build node hierarchy
-        /// todo: get bone from stack
-        /// todo: make map of aiBone* to aiNode*
-        /// then update convert clusters to the new format
-        void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node) {
-            const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(id, "Model");
-
-            std::vector<aiNode*> nodes;
-            nodes.reserve(conns.size());
-
-            std::vector<aiNode*> nodes_chain;
-            std::vector<aiNode*> post_nodes_chain;
-
-            try {
-                for (const Connection* con : conns) {
-                    // ignore object-property links
-                    if (con->PropertyName().length()) {
-                        // really important we document why this is ignored.
-                        FBXImporter::LogInfo("ignoring property link - no docs on why this is ignored");
-                        continue; //?
-                    }
-
-                    // convert connection source object into Object base class
-                    const Object* const object = con->SourceObject();
-                    if (nullptr == object) {
-                        FBXImporter::LogError("failed to convert source object for Model link");
-                        continue;
-                    }
-
-                    // FBX Model::Cube, Model::Bone001, etc elements
-                    // This detects if we can cast the object into this model structure.
-                    const Model* const model = dynamic_cast<const Model*>(object);
-
-                    if (nullptr != model) {
-                        nodes_chain.clear();
-                        post_nodes_chain.clear();
-
-                        aiMatrix4x4 new_abs_transform = parent->mTransformation;
-                        std::string node_name = FixNodeName(model->Name());
-                        // even though there is only a single input node, the design of
-                        // assimp (or rather: the complicated transformation chain that
-                        // is employed by fbx) means that we may need multiple aiNode's
-                        // to represent a fbx node's transformation.
-
-
-                        // generate node transforms - this includes pivot data
-                        // if need_additional_node is true then you t
-                        const bool need_additional_node = GenerateTransformationNodeChain(*model, node_name, nodes_chain, post_nodes_chain);
-
-                        // assert that for the current node we must have at least a single transform
-                        ai_assert(nodes_chain.size());
-
-                        if (need_additional_node) {
-                            nodes_chain.push_back(new aiNode(node_name));
-                        }
-
-                        //setup metadata on newest node
-                        SetupNodeMetadata(*model, *nodes_chain.back());
-
-                        // link all nodes in a row
-                        aiNode* last_parent = parent;
-                        for (aiNode* child : nodes_chain) {
-                            ai_assert(child);
-
-                            if (last_parent != parent) {
-                                last_parent->mNumChildren = 1;
-                                last_parent->mChildren = new aiNode*[1];
-                                last_parent->mChildren[0] = child;
-                            }
-
-                            child->mParent = last_parent;
-                            last_parent = child;
-
-                            new_abs_transform *= child->mTransformation;
-                        }
-
-                        // attach geometry
-                        ConvertModel(*model, nodes_chain.back(), root_node, new_abs_transform);
-
-                        // check if there will be any child nodes
-                        const std::vector<const Connection*>& child_conns
-                            = doc.GetConnectionsByDestinationSequenced(model->ID(), "Model");
-
-                        // if so, link the geometric transform inverse nodes
-                        // before we attach any child nodes
-                        if (child_conns.size()) {
-                            for (aiNode* postnode : post_nodes_chain) {
-                                ai_assert(postnode);
-
-                                if (last_parent != parent) {
-                                    last_parent->mNumChildren = 1;
-                                    last_parent->mChildren = new aiNode*[1];
-                                    last_parent->mChildren[0] = postnode;
-                                }
-
-                                postnode->mParent = last_parent;
-                                last_parent = postnode;
-
-                                new_abs_transform *= postnode->mTransformation;
-                            }
-                        }
-                        else {
-                            // free the nodes we allocated as we don't need them
-                            Util::delete_fun<aiNode> deleter;
-                            std::for_each(
-                                post_nodes_chain.begin(),
-                                post_nodes_chain.end(),
-                                deleter
-                            );
-                        }
-
-                        // recursion call - child nodes
-                        ConvertNodes(model->ID(), last_parent, root_node);
-
-                        if (doc.Settings().readLights) {
-                            ConvertLights(*model, node_name);
-                        }
-
-                        if (doc.Settings().readCameras) {
-                            ConvertCameras(*model, node_name);
-                        }
-
-                        nodes.push_back(nodes_chain.front());
-                        nodes_chain.clear();
-                    }
-                }
-
-                if (nodes.size()) {
-                    parent->mChildren = new aiNode*[nodes.size()]();
-                    parent->mNumChildren = static_cast<unsigned int>(nodes.size());
-
-                    std::swap_ranges(nodes.begin(), nodes.end(), parent->mChildren);
-                }
-                else
-                {
-                    parent->mNumChildren = 0;
-                    parent->mChildren = nullptr;
-                }
-                
-            }
-            catch (std::exception&) {
-                Util::delete_fun<aiNode> deleter;
-                std::for_each(nodes.begin(), nodes.end(), deleter);
-                std::for_each(nodes_chain.begin(), nodes_chain.end(), deleter);
-                std::for_each(post_nodes_chain.begin(), post_nodes_chain.end(), deleter);
-            }
-        }
-
-
-        void FBXConverter::ConvertLights(const Model& model, const std::string &orig_name) {
-            const std::vector<const NodeAttribute*>& node_attrs = model.GetAttributes();
-            for (const NodeAttribute* attr : node_attrs) {
-                const Light* const light = dynamic_cast<const Light*>(attr);
-                if (light) {
-                    ConvertLight(*light, orig_name);
-                }
-            }
-        }
-
-        void FBXConverter::ConvertCameras(const Model& model, const std::string &orig_name) {
-            const std::vector<const NodeAttribute*>& node_attrs = model.GetAttributes();
-            for (const NodeAttribute* attr : node_attrs) {
-                const Camera* const cam = dynamic_cast<const Camera*>(attr);
-                if (cam) {
-                    ConvertCamera(*cam, orig_name);
-                }
-            }
-        }
-
-        void FBXConverter::ConvertLight(const Light& light, const std::string &orig_name) {
-            lights.push_back(new aiLight());
-            aiLight* const out_light = lights.back();
-
-            out_light->mName.Set(orig_name);
-
-            const float intensity = light.Intensity() / 100.0f;
-            const aiVector3D& col = light.Color();
-
-            out_light->mColorDiffuse = aiColor3D(col.x, col.y, col.z);
-            out_light->mColorDiffuse.r *= intensity;
-            out_light->mColorDiffuse.g *= intensity;
-            out_light->mColorDiffuse.b *= intensity;
-
-            out_light->mColorSpecular = out_light->mColorDiffuse;
-
-            //lights are defined along negative y direction
-            out_light->mPosition = aiVector3D(0.0f);
-            out_light->mDirection = aiVector3D(0.0f, -1.0f, 0.0f);
-            out_light->mUp = aiVector3D(0.0f, 0.0f, -1.0f);
-
-            switch (light.LightType())
-            {
-            case Light::Type_Point:
-                out_light->mType = aiLightSource_POINT;
-                break;
-
-            case Light::Type_Directional:
-                out_light->mType = aiLightSource_DIRECTIONAL;
-                break;
-
-            case Light::Type_Spot:
-                out_light->mType = aiLightSource_SPOT;
-                out_light->mAngleOuterCone = AI_DEG_TO_RAD(light.OuterAngle());
-                out_light->mAngleInnerCone = AI_DEG_TO_RAD(light.InnerAngle());
-                break;
-
-            case Light::Type_Area:
-                FBXImporter::LogWarn("cannot represent area light, set to UNDEFINED");
-                out_light->mType = aiLightSource_UNDEFINED;
-                break;
-
-            case Light::Type_Volume:
-                FBXImporter::LogWarn("cannot represent volume light, set to UNDEFINED");
-                out_light->mType = aiLightSource_UNDEFINED;
-                break;
-            default:
-                ai_assert(false);
-            }
-
-            float decay = light.DecayStart();
-            switch (light.DecayType())
-            {
-            case Light::Decay_None:
-                out_light->mAttenuationConstant = decay;
-                out_light->mAttenuationLinear = 0.0f;
-                out_light->mAttenuationQuadratic = 0.0f;
-                break;
-            case Light::Decay_Linear:
-                out_light->mAttenuationConstant = 0.0f;
-                out_light->mAttenuationLinear = 2.0f / decay;
-                out_light->mAttenuationQuadratic = 0.0f;
-                break;
-            case Light::Decay_Quadratic:
-                out_light->mAttenuationConstant = 0.0f;
-                out_light->mAttenuationLinear = 0.0f;
-                out_light->mAttenuationQuadratic = 2.0f / (decay * decay);
-                break;
-            case Light::Decay_Cubic:
-                FBXImporter::LogWarn("cannot represent cubic attenuation, set to Quadratic");
-                out_light->mAttenuationQuadratic = 1.0f;
-                break;
-            default:
-                ai_assert(false);
-                break;
-            }
-        }
-
-        void FBXConverter::ConvertCamera(const Camera& cam, const std::string &orig_name)
-        {
-            cameras.push_back(new aiCamera());
-            aiCamera* const out_camera = cameras.back();
-
-            out_camera->mName.Set(orig_name);
-
-            out_camera->mAspect = cam.AspectWidth() / cam.AspectHeight();
-
-            out_camera->mPosition = aiVector3D(0.0f);
-            out_camera->mLookAt = aiVector3D(1.0f, 0.0f, 0.0f);
-            out_camera->mUp = aiVector3D(0.0f, 1.0f, 0.0f);
-
-            out_camera->mHorizontalFOV = AI_DEG_TO_RAD(cam.FieldOfView());
-
-            out_camera->mClipPlaneNear = cam.NearPlane();
-            out_camera->mClipPlaneFar = cam.FarPlane();
-
-            out_camera->mHorizontalFOV = AI_DEG_TO_RAD(cam.FieldOfView());
-            out_camera->mClipPlaneNear = cam.NearPlane();
-            out_camera->mClipPlaneFar = cam.FarPlane();
-        }
-
-        void FBXConverter::GetUniqueName(const std::string &name, std::string &uniqueName)
-        {
-            uniqueName = name;
-            auto it_pair = mNodeNames.insert({ name, 0 }); // duplicate node name instance count
-            unsigned int& i = it_pair.first->second;
-            while (!it_pair.second)
-            {
-                i++;
-                std::ostringstream ext;
-                ext << name << std::setfill('0') << std::setw(3) << i;
-                uniqueName = ext.str();
-                it_pair = mNodeNames.insert({ uniqueName, 0 });
-            }
-        }
-
-        const char* FBXConverter::NameTransformationComp(TransformationComp comp) {
-            switch (comp) {
-            case TransformationComp_Translation:
-                return "Translation";
-            case TransformationComp_RotationOffset:
-                return "RotationOffset";
-            case TransformationComp_RotationPivot:
-                return "RotationPivot";
-            case TransformationComp_PreRotation:
-                return "PreRotation";
-            case TransformationComp_Rotation:
-                return "Rotation";
-            case TransformationComp_PostRotation:
-                return "PostRotation";
-            case TransformationComp_RotationPivotInverse:
-                return "RotationPivotInverse";
-            case TransformationComp_ScalingOffset:
-                return "ScalingOffset";
-            case TransformationComp_ScalingPivot:
-                return "ScalingPivot";
-            case TransformationComp_Scaling:
-                return "Scaling";
-            case TransformationComp_ScalingPivotInverse:
-                return "ScalingPivotInverse";
-            case TransformationComp_GeometricScaling:
-                return "GeometricScaling";
-            case TransformationComp_GeometricRotation:
-                return "GeometricRotation";
-            case TransformationComp_GeometricTranslation:
-                return "GeometricTranslation";
-            case TransformationComp_GeometricScalingInverse:
-                return "GeometricScalingInverse";
-            case TransformationComp_GeometricRotationInverse:
-                return "GeometricRotationInverse";
-            case TransformationComp_GeometricTranslationInverse:
-                return "GeometricTranslationInverse";
-            case TransformationComp_MAXIMUM: // this is to silence compiler warnings
-            default:
-                break;
-            }
-
-            ai_assert(false);
-
-            return nullptr;
-        }
-
-        const char* FBXConverter::NameTransformationCompProperty(TransformationComp comp) {
-            switch (comp) {
-            case TransformationComp_Translation:
-                return "Lcl Translation";
-            case TransformationComp_RotationOffset:
-                return "RotationOffset";
-            case TransformationComp_RotationPivot:
-                return "RotationPivot";
-            case TransformationComp_PreRotation:
-                return "PreRotation";
-            case TransformationComp_Rotation:
-                return "Lcl Rotation";
-            case TransformationComp_PostRotation:
-                return "PostRotation";
-            case TransformationComp_RotationPivotInverse:
-                return "RotationPivotInverse";
-            case TransformationComp_ScalingOffset:
-                return "ScalingOffset";
-            case TransformationComp_ScalingPivot:
-                return "ScalingPivot";
-            case TransformationComp_Scaling:
-                return "Lcl Scaling";
-            case TransformationComp_ScalingPivotInverse:
-                return "ScalingPivotInverse";
-            case TransformationComp_GeometricScaling:
-                return "GeometricScaling";
-            case TransformationComp_GeometricRotation:
-                return "GeometricRotation";
-            case TransformationComp_GeometricTranslation:
-                return "GeometricTranslation";
-            case TransformationComp_GeometricScalingInverse:
-                return "GeometricScalingInverse";
-            case TransformationComp_GeometricRotationInverse:
-                return "GeometricRotationInverse";
-            case TransformationComp_GeometricTranslationInverse:
-                return "GeometricTranslationInverse";
-            case TransformationComp_MAXIMUM: // this is to silence compiler warnings
-                break;
-            }
-
-            ai_assert(false);
-
-            return nullptr;
-        }
-
-        aiVector3D FBXConverter::TransformationCompDefaultValue(TransformationComp comp)
-        {
-            // XXX a neat way to solve the never-ending special cases for scaling
-            // would be to do everything in log space!
-            return comp == TransformationComp_Scaling ? aiVector3D(1.f, 1.f, 1.f) : aiVector3D();
-        }
-
-        void FBXConverter::GetRotationMatrix(Model::RotOrder mode, const aiVector3D& rotation, aiMatrix4x4& out)
-        {
-            if (mode == Model::RotOrder_SphericXYZ) {
-                FBXImporter::LogError("Unsupported RotationMode: SphericXYZ");
-                out = aiMatrix4x4();
-                return;
-            }
-
-            const float angle_epsilon = Math::getEpsilon<float>();
-
-            out = aiMatrix4x4();
-
-            bool is_id[3] = { true, true, true };
-
-            aiMatrix4x4 temp[3];
-            if (std::fabs(rotation.z) > angle_epsilon) {
-                aiMatrix4x4::RotationZ(AI_DEG_TO_RAD(rotation.z), temp[2]);
-                is_id[2] = false;
-            }
-            if (std::fabs(rotation.y) > angle_epsilon) {
-                aiMatrix4x4::RotationY(AI_DEG_TO_RAD(rotation.y), temp[1]);
-                is_id[1] = false;
-            }
-            if (std::fabs(rotation.x) > angle_epsilon) {
-                aiMatrix4x4::RotationX(AI_DEG_TO_RAD(rotation.x), temp[0]);
-                is_id[0] = false;
-            }
-
-            int order[3] = { -1, -1, -1 };
-
-            // note: rotation order is inverted since we're left multiplying as is usual in assimp
-            switch (mode)
-            {
-            case Model::RotOrder_EulerXYZ:
-                order[0] = 2;
-                order[1] = 1;
-                order[2] = 0;
-                break;
-
-            case Model::RotOrder_EulerXZY:
-                order[0] = 1;
-                order[1] = 2;
-                order[2] = 0;
-                break;
-
-            case Model::RotOrder_EulerYZX:
-                order[0] = 0;
-                order[1] = 2;
-                order[2] = 1;
-                break;
-
-            case Model::RotOrder_EulerYXZ:
-                order[0] = 2;
-                order[1] = 0;
-                order[2] = 1;
-                break;
-
-            case Model::RotOrder_EulerZXY:
-                order[0] = 1;
-                order[1] = 0;
-                order[2] = 2;
-                break;
-
-            case Model::RotOrder_EulerZYX:
-                order[0] = 0;
-                order[1] = 1;
-                order[2] = 2;
-                break;
-
-            default:
-                ai_assert(false);
-                break;
-            }
-
-            ai_assert(order[0] >= 0);
-            ai_assert(order[0] <= 2);
-            ai_assert(order[1] >= 0);
-            ai_assert(order[1] <= 2);
-            ai_assert(order[2] >= 0);
-            ai_assert(order[2] <= 2);
-
-            if (!is_id[order[0]]) {
-                out = temp[order[0]];
-            }
-
-            if (!is_id[order[1]]) {
-                out = out * temp[order[1]];
-            }
-
-            if (!is_id[order[2]]) {
-                out = out * temp[order[2]];
-            }
-        }
-
-        bool FBXConverter::NeedsComplexTransformationChain(const Model& model)
-        {
-            const PropertyTable& props = model.Props();
-            bool ok;
-
-            const float zero_epsilon = 1e-6f;
-            const aiVector3D all_ones(1.0f, 1.0f, 1.0f);
-            for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i) {
-                const TransformationComp comp = static_cast<TransformationComp>(i);
-
-                if (comp == TransformationComp_Rotation || comp == TransformationComp_Scaling || comp == TransformationComp_Translation) {
-                    continue;
-                }
-
-                bool scale_compare = (comp == TransformationComp_GeometricScaling || comp == TransformationComp_Scaling);
-
-                const aiVector3D& v = PropertyGet<aiVector3D>(props, NameTransformationCompProperty(comp), ok);
-                if (ok && scale_compare) {
-                    if ((v - all_ones).SquareLength() > zero_epsilon) {
-                        return true;
-                    }
-                } else if (ok) {
-                    if (v.SquareLength() > zero_epsilon) {
-                        return true;
-                    }
-                }
-            }
-
-            return false;
-        }
-
-        std::string FBXConverter::NameTransformationChainNode(const std::string& name, TransformationComp comp)
-        {
-            return name + std::string(MAGIC_NODE_TAG) + "_" + NameTransformationComp(comp);
-        }
-
-        bool FBXConverter::GenerateTransformationNodeChain(const Model& model, const std::string& name, std::vector<aiNode*>& output_nodes,
-            std::vector<aiNode*>& post_output_nodes) {
-            const PropertyTable& props = model.Props();
-            const Model::RotOrder rot = model.RotationOrder();
-
-            bool ok;
-
-            aiMatrix4x4 chain[TransformationComp_MAXIMUM];
-
-            ai_assert(TransformationComp_MAXIMUM < 32);
-            std::uint32_t chainBits = 0;
-            // A node won't need a node chain if it only has these.
-            const std::uint32_t chainMaskSimple = (1 << TransformationComp_Translation) + (1 << TransformationComp_Scaling) + (1 << TransformationComp_Rotation);
-            // A node will need a node chain if it has any of these.
-            const std::uint32_t chainMaskComplex = ((1 << (TransformationComp_MAXIMUM)) - 1) - chainMaskSimple;
-
-            std::fill_n(chain, static_cast<unsigned int>(TransformationComp_MAXIMUM), aiMatrix4x4());
-
-            // generate transformation matrices for all the different transformation components
-            const float zero_epsilon = Math::getEpsilon<float>();
-            const aiVector3D all_ones(1.0f, 1.0f, 1.0f);
-
-            const aiVector3D& PreRotation = PropertyGet<aiVector3D>(props, "PreRotation", ok);
-            if (ok && PreRotation.SquareLength() > zero_epsilon) {
-                chainBits = chainBits | (1 << TransformationComp_PreRotation);
-
-                GetRotationMatrix(Model::RotOrder::RotOrder_EulerXYZ, PreRotation, chain[TransformationComp_PreRotation]);
-            }
-
-            const aiVector3D& PostRotation = PropertyGet<aiVector3D>(props, "PostRotation", ok);
-            if (ok && PostRotation.SquareLength() > zero_epsilon) {
-                chainBits = chainBits | (1 << TransformationComp_PostRotation);
-
-                GetRotationMatrix(Model::RotOrder::RotOrder_EulerXYZ, PostRotation, chain[TransformationComp_PostRotation]);
-            }
-
-            const aiVector3D& RotationPivot = PropertyGet<aiVector3D>(props, "RotationPivot", ok);
-            if (ok && RotationPivot.SquareLength() > zero_epsilon) {
-                chainBits = chainBits | (1 << TransformationComp_RotationPivot) | (1 << TransformationComp_RotationPivotInverse);
-
-                aiMatrix4x4::Translation(RotationPivot, chain[TransformationComp_RotationPivot]);
-                aiMatrix4x4::Translation(-RotationPivot, chain[TransformationComp_RotationPivotInverse]);
-            }
-
-            const aiVector3D& RotationOffset = PropertyGet<aiVector3D>(props, "RotationOffset", ok);
-            if (ok && RotationOffset.SquareLength() > zero_epsilon) {
-                chainBits = chainBits | (1 << TransformationComp_RotationOffset);
-
-                aiMatrix4x4::Translation(RotationOffset, chain[TransformationComp_RotationOffset]);
-            }
-
-            const aiVector3D& ScalingOffset = PropertyGet<aiVector3D>(props, "ScalingOffset", ok);
-            if (ok && ScalingOffset.SquareLength() > zero_epsilon) {
-                chainBits = chainBits | (1 << TransformationComp_ScalingOffset);
-
-                aiMatrix4x4::Translation(ScalingOffset, chain[TransformationComp_ScalingOffset]);
-            }
-
-            const aiVector3D& ScalingPivot = PropertyGet<aiVector3D>(props, "ScalingPivot", ok);
-            if (ok && ScalingPivot.SquareLength() > zero_epsilon) {
-                chainBits = chainBits | (1 << TransformationComp_ScalingPivot) | (1 << TransformationComp_ScalingPivotInverse);
-
-                aiMatrix4x4::Translation(ScalingPivot, chain[TransformationComp_ScalingPivot]);
-                aiMatrix4x4::Translation(-ScalingPivot, chain[TransformationComp_ScalingPivotInverse]);
-            }
-
-            const aiVector3D& Translation = PropertyGet<aiVector3D>(props, "Lcl Translation", ok);
-            if (ok && Translation.SquareLength() > zero_epsilon) {
-                chainBits = chainBits | (1 << TransformationComp_Translation);
-
-                aiMatrix4x4::Translation(Translation, chain[TransformationComp_Translation]);
-            }
-
-            const aiVector3D& Scaling = PropertyGet<aiVector3D>(props, "Lcl Scaling", ok);
-            if (ok && (Scaling - all_ones).SquareLength() > zero_epsilon) {
-                chainBits = chainBits | (1 << TransformationComp_Scaling);
-
-                aiMatrix4x4::Scaling(Scaling, chain[TransformationComp_Scaling]);
-            }
-
-            const aiVector3D& Rotation = PropertyGet<aiVector3D>(props, "Lcl Rotation", ok);
-            if (ok && Rotation.SquareLength() > zero_epsilon) {
-                chainBits = chainBits | (1 << TransformationComp_Rotation);
-
-                GetRotationMatrix(rot, Rotation, chain[TransformationComp_Rotation]);
-            }
-
-            const aiVector3D& GeometricScaling = PropertyGet<aiVector3D>(props, "GeometricScaling", ok);
-            if (ok && (GeometricScaling - all_ones).SquareLength() > zero_epsilon) {
-                chainBits = chainBits | (1 << TransformationComp_GeometricScaling);
-                aiMatrix4x4::Scaling(GeometricScaling, chain[TransformationComp_GeometricScaling]);
-                aiVector3D GeometricScalingInverse = GeometricScaling;
-                bool canscale = true;
-                for (unsigned int i = 0; i < 3; ++i) {
-                    if (std::fabs(GeometricScalingInverse[i]) > zero_epsilon) {
-                        GeometricScalingInverse[i] = 1.0f / GeometricScaling[i];
-                    }
-                    else {
-                        FBXImporter::LogError("cannot invert geometric scaling matrix with a 0.0 scale component");
-                        canscale = false;
-                        break;
-                    }
-                }
-                if (canscale) {
-                    chainBits = chainBits | (1 << TransformationComp_GeometricScalingInverse);
-                    aiMatrix4x4::Scaling(GeometricScalingInverse, chain[TransformationComp_GeometricScalingInverse]);
-                }
-            }
-
-            const aiVector3D& GeometricRotation = PropertyGet<aiVector3D>(props, "GeometricRotation", ok);
-            if (ok && GeometricRotation.SquareLength() > zero_epsilon) {
-                chainBits = chainBits | (1 << TransformationComp_GeometricRotation) | (1 << TransformationComp_GeometricRotationInverse);
-                GetRotationMatrix(rot, GeometricRotation, chain[TransformationComp_GeometricRotation]);
-                GetRotationMatrix(rot, GeometricRotation, chain[TransformationComp_GeometricRotationInverse]);
-                chain[TransformationComp_GeometricRotationInverse].Inverse();
-            }
-
-            const aiVector3D& GeometricTranslation = PropertyGet<aiVector3D>(props, "GeometricTranslation", ok);
-            if (ok && GeometricTranslation.SquareLength() > zero_epsilon) {
-                chainBits = chainBits | (1 << TransformationComp_GeometricTranslation) | (1 << TransformationComp_GeometricTranslationInverse);
-                aiMatrix4x4::Translation(GeometricTranslation, chain[TransformationComp_GeometricTranslation]);
-                aiMatrix4x4::Translation(-GeometricTranslation, chain[TransformationComp_GeometricTranslationInverse]);
-            }
-
-            // is_complex needs to be consistent with NeedsComplexTransformationChain()
-            // or the interplay between this code and the animation converter would
-            // not be guaranteed.
-            //ai_assert(NeedsComplexTransformationChain(model) == ((chainBits & chainMaskComplex) != 0));
-
-            // now, if we have more than just Translation, Scaling and Rotation,
-            // we need to generate a full node chain to accommodate for assimp's
-            // lack to express pivots and offsets.
-            if ((chainBits & chainMaskComplex) && doc.Settings().preservePivots) {
-                FBXImporter::LogInfo("generating full transformation chain for node: " + name);
-
-                // query the anim_chain_bits dictionary to find out which chain elements
-                // have associated node animation channels. These can not be dropped
-                // even if they have identity transform in bind pose.
-                NodeAnimBitMap::const_iterator it = node_anim_chain_bits.find(name);
-                const unsigned int anim_chain_bitmask = (it == node_anim_chain_bits.end() ? 0 : (*it).second);
-
-                unsigned int bit = 0x1;
-                for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i, bit <<= 1) {
-                    const TransformationComp comp = static_cast<TransformationComp>(i);
-
-                    if ((chainBits & bit) == 0 && (anim_chain_bitmask & bit) == 0) {
-                        continue;
-                    }
-
-                    if (comp == TransformationComp_PostRotation) {
-                        chain[i] = chain[i].Inverse();
-                    }
-
-                    aiNode* nd = new aiNode();
-                    nd->mName.Set(NameTransformationChainNode(name, comp));
-                    nd->mTransformation = chain[i];
-
-                    // geometric inverses go in a post-node chain
-                    if (comp == TransformationComp_GeometricScalingInverse ||
-                        comp == TransformationComp_GeometricRotationInverse ||
-                        comp == TransformationComp_GeometricTranslationInverse
-                        ) {
-                        post_output_nodes.push_back(nd);
-                    }
-                    else {
-                        output_nodes.push_back(nd);
-                    }
-                }
-
-                ai_assert(output_nodes.size());
-                return true;
-            }
-
-            // else, we can just multiply the matrices together
-            aiNode* nd = new aiNode();
-            output_nodes.push_back(nd);
-
-            // name passed to the method is already unique
-            nd->mName.Set(name);
-
-            for (const auto &transform : chain) {
-                nd->mTransformation = nd->mTransformation * transform;
-            }
-            return false;
-        }
-
-        void FBXConverter::SetupNodeMetadata(const Model& model, aiNode& nd)
-        {
-            const PropertyTable& props = model.Props();
-            DirectPropertyMap unparsedProperties = props.GetUnparsedProperties();
-
-            // create metadata on node
-            const std::size_t numStaticMetaData = 2;
-            aiMetadata* data = aiMetadata::Alloc(static_cast<unsigned int>(unparsedProperties.size() + numStaticMetaData));
-            nd.mMetaData = data;
-            int index = 0;
-
-            // find user defined properties (3ds Max)
-            data->Set(index++, "UserProperties", aiString(PropertyGet<std::string>(props, "UDP3DSMAX", "")));
-            // preserve the info that a node was marked as Null node in the original file.
-            data->Set(index++, "IsNull", model.IsNull() ? true : false);
-
-            // add unparsed properties to the node's metadata
-            for (const DirectPropertyMap::value_type& prop : unparsedProperties) {
-                // Interpret the property as a concrete type
-                if (const TypedProperty<bool>* interpreted = prop.second->As<TypedProperty<bool> >()) {
-                    data->Set(index++, prop.first, interpreted->Value());
-                }
-                else if (const TypedProperty<int>* interpreted = prop.second->As<TypedProperty<int> >()) {
-                    data->Set(index++, prop.first, interpreted->Value());
-                }
-                else if (const TypedProperty<uint64_t>* interpreted = prop.second->As<TypedProperty<uint64_t> >()) {
-                    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<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 {
-                    ai_assert(false);
-                }
-            }
-        }
-
-        void FBXConverter::ConvertModel(const Model &model, aiNode *parent, aiNode *root_node,
-                                        const aiMatrix4x4 &absolute_transform)
-        {
-            const std::vector<const Geometry*>& geos = model.GetGeometry();
-
-            std::vector<unsigned int> meshes;
-            meshes.reserve(geos.size());
-
-            for (const Geometry* geo : geos) {
-
-                const MeshGeometry* const mesh = dynamic_cast<const MeshGeometry*>(geo);
-                const LineGeometry* const line = dynamic_cast<const LineGeometry*>(geo);
-                if (mesh) {
-                    const std::vector<unsigned int>& indices = ConvertMesh(*mesh, model, parent, root_node,
-                                                                           absolute_transform);
-                    std::copy(indices.begin(), indices.end(), std::back_inserter(meshes));
-                }
-                else if (line) {
-                    const std::vector<unsigned int>& indices = ConvertLine(*line, model, parent, root_node);
-                    std::copy(indices.begin(), indices.end(), std::back_inserter(meshes));
-                }
-                else {
-                    FBXImporter::LogWarn("ignoring unrecognized geometry: " + geo->Name());
-                }
-            }
-
-            if (meshes.size()) {
-                parent->mMeshes = new unsigned int[meshes.size()]();
-                parent->mNumMeshes = static_cast<unsigned int>(meshes.size());
-
-                std::swap_ranges(meshes.begin(), meshes.end(), parent->mMeshes);
-            }
-        }
-
-        std::vector<unsigned int>
-        FBXConverter::ConvertMesh(const MeshGeometry &mesh, const Model &model, aiNode *parent, aiNode *root_node,
-                                  const aiMatrix4x4 &absolute_transform)
-        {
-            std::vector<unsigned int> temp;
-
-            MeshMap::const_iterator it = meshes_converted.find(&mesh);
-            if (it != meshes_converted.end()) {
-                std::copy((*it).second.begin(), (*it).second.end(), std::back_inserter(temp));
-                return temp;
-            }
-
-            const std::vector<aiVector3D>& vertices = mesh.GetVertices();
-            const std::vector<unsigned int>& faces = mesh.GetFaceIndexCounts();
-            if (vertices.empty() || faces.empty()) {
-                FBXImporter::LogWarn("ignoring empty geometry: " + mesh.Name());
-                return temp;
-            }
-
-            // one material per mesh maps easily to aiMesh. Multiple material
-            // meshes need to be split.
-            const MatIndexArray& mindices = mesh.GetMaterialIndices();
-            if (doc.Settings().readMaterials && !mindices.empty()) {
-                const MatIndexArray::value_type base = mindices[0];
-                for (MatIndexArray::value_type index : mindices) {
-                    if (index != base) {
-                        return ConvertMeshMultiMaterial(mesh, model, parent, root_node, absolute_transform);
-                    }
-                }
-            }
-
-            // faster code-path, just copy the data
-            temp.push_back(ConvertMeshSingleMaterial(mesh, model, absolute_transform, parent, root_node));
-            return temp;
-        }
-
-        std::vector<unsigned int> FBXConverter::ConvertLine(const LineGeometry& line, const Model& model,
-                                                            aiNode *parent, aiNode *root_node)
-        {
-            std::vector<unsigned int> temp;
-
-            const std::vector<aiVector3D>& vertices = line.GetVertices();
-            const std::vector<int>& indices = line.GetIndices();
-            if (vertices.empty() || indices.empty()) {
-                FBXImporter::LogWarn("ignoring empty line: " + line.Name());
-                return temp;
-            }
-
-            aiMesh* const out_mesh = SetupEmptyMesh(line, root_node);
-            out_mesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
-
-            // copy vertices
-            out_mesh->mNumVertices = static_cast<unsigned int>(vertices.size());
-            out_mesh->mVertices = new aiVector3D[out_mesh->mNumVertices];
-            std::copy(vertices.begin(), vertices.end(), out_mesh->mVertices);
-
-            //Number of line segments (faces) is "Number of Points - Number of Endpoints"
-            //N.B.: Endpoints in FbxLine are denoted by negative indices.
-            //If such an Index is encountered, add 1 and multiply by -1 to get the real index.
-            unsigned int epcount = 0;
-            for (unsigned i = 0; i < indices.size(); i++)
-            {
-                if (indices[i] < 0) {
-                    epcount++;
-                }
-            }
-            unsigned int pcount = static_cast<unsigned int>( indices.size() );
-            unsigned int scount = out_mesh->mNumFaces = pcount - epcount;
-
-            aiFace* fac = out_mesh->mFaces = new aiFace[scount]();
-            for (unsigned int i = 0; i < pcount; ++i) {
-                if (indices[i] < 0) continue;
-                aiFace& f = *fac++;
-                f.mNumIndices = 2; //2 == aiPrimitiveType_LINE 
-                f.mIndices = new unsigned int[2];
-                f.mIndices[0] = indices[i];
-                int segid = indices[(i + 1 == pcount ? 0 : i + 1)];   //If we have reached he last point, wrap around
-                f.mIndices[1] = (segid < 0 ? (segid + 1)*-1 : segid); //Convert EndPoint Index to normal Index
-            }
-            temp.push_back(static_cast<unsigned int>(meshes.size() - 1));
-            return temp;
-        }
-
-        aiMesh* FBXConverter::SetupEmptyMesh(const Geometry& mesh, aiNode *parent)
-        {
-            aiMesh* const out_mesh = new aiMesh();
-            meshes.push_back(out_mesh);
-            meshes_converted[&mesh].push_back(static_cast<unsigned int>(meshes.size() - 1));
-
-            // set name
-            std::string name = mesh.Name();
-            if (name.substr(0, 10) == "Geometry::") {
-                name = name.substr(10);
-            }
-
-            if (name.length()) {
-                out_mesh->mName.Set(name);
-            }
-            else
-            {
-                out_mesh->mName = parent->mName;
-            }
-
-            return out_mesh;
-        }
-
-        unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry &mesh, const Model &model,
-                                                             const aiMatrix4x4 &absolute_transform, aiNode *parent,
-                                                             aiNode *root_node)
-        {
-            const MatIndexArray& mindices = mesh.GetMaterialIndices();
-            aiMesh* const out_mesh = SetupEmptyMesh(mesh, parent);
-
-            const std::vector<aiVector3D>& vertices = mesh.GetVertices();
-            const std::vector<unsigned int>& faces = mesh.GetFaceIndexCounts();
-
-            // copy vertices
-            out_mesh->mNumVertices = static_cast<unsigned int>(vertices.size());
-            out_mesh->mVertices = new aiVector3D[vertices.size()];
-
-            std::copy(vertices.begin(), vertices.end(), out_mesh->mVertices);
-
-            // generate dummy faces
-            out_mesh->mNumFaces = static_cast<unsigned int>(faces.size());
-            aiFace* fac = out_mesh->mFaces = new aiFace[faces.size()]();
-
-            unsigned int cursor = 0;
-            for (unsigned int pcount : faces) {
-                aiFace& f = *fac++;
-                f.mNumIndices = pcount;
-                f.mIndices = new unsigned int[pcount];
-                switch (pcount)
-                {
-                case 1:
-                    out_mesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
-                    break;
-                case 2:
-                    out_mesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
-                    break;
-                case 3:
-                    out_mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
-                    break;
-                default:
-                    out_mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
-                    break;
-                }
-                for (unsigned int i = 0; i < pcount; ++i) {
-                    f.mIndices[i] = cursor++;
-                }
-            }
-
-            // copy normals
-            const std::vector<aiVector3D>& normals = mesh.GetNormals();
-            if (normals.size()) {
-                ai_assert(normals.size() == vertices.size());
-
-                out_mesh->mNormals = new aiVector3D[vertices.size()];
-                std::copy(normals.begin(), normals.end(), out_mesh->mNormals);
-            }
-
-            // copy tangents - assimp requires both tangents and bitangents (binormals)
-            // to be present, or neither of them. Compute binormals from normals
-            // and tangents if needed.
-            const std::vector<aiVector3D>& tangents = mesh.GetTangents();
-            const std::vector<aiVector3D>* binormals = &mesh.GetBinormals();
-
-            if (tangents.size()) {
-                std::vector<aiVector3D> tempBinormals;
-                if (!binormals->size()) {
-                    if (normals.size()) {
-                        tempBinormals.resize(normals.size());
-                        for (unsigned int i = 0; i < tangents.size(); ++i) {
-                            tempBinormals[i] = normals[i] ^ tangents[i];
-                        }
-
-                        binormals = &tempBinormals;
-                    }
-                    else {
-                        binormals = nullptr;
-                    }
-                }
-
-                if (binormals) {
-                    ai_assert(tangents.size() == vertices.size());
-                    ai_assert(binormals->size() == vertices.size());
-
-                    out_mesh->mTangents = new aiVector3D[vertices.size()];
-                    std::copy(tangents.begin(), tangents.end(), out_mesh->mTangents);
-
-                    out_mesh->mBitangents = new aiVector3D[vertices.size()];
-                    std::copy(binormals->begin(), binormals->end(), out_mesh->mBitangents);
-                }
-            }
-
-            // copy texture coords
-            for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
-                const std::vector<aiVector2D>& uvs = mesh.GetTextureCoords(i);
-                if (uvs.empty()) {
-                    break;
-                }
-
-                aiVector3D* out_uv = out_mesh->mTextureCoords[i] = new aiVector3D[vertices.size()];
-                for (const aiVector2D& v : uvs) {
-                    *out_uv++ = aiVector3D(v.x, v.y, 0.0f);
-                }
-
-                out_mesh->mNumUVComponents[i] = 2;
-            }
-
-            // copy vertex colors
-            for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) {
-                const std::vector<aiColor4D>& colors = mesh.GetVertexColors(i);
-                if (colors.empty()) {
-                    break;
-                }
-
-                out_mesh->mColors[i] = new aiColor4D[vertices.size()];
-                std::copy(colors.begin(), colors.end(), out_mesh->mColors[i]);
-            }
-
-            if (!doc.Settings().readMaterials || mindices.empty()) {
-                FBXImporter::LogError("no material assigned to mesh, setting default material");
-                out_mesh->mMaterialIndex = GetDefaultMaterial();
-            }
-            else {
-                ConvertMaterialForMesh(out_mesh, model, mesh, mindices[0]);
-            }
-
-            if (doc.Settings().readWeights && mesh.DeformerSkin() != nullptr) {
-                ConvertWeights(out_mesh, model, mesh, absolute_transform, parent, root_node, NO_MATERIAL_SEPARATION,
-                               nullptr);
-            }
-
-            std::vector<aiAnimMesh*> animMeshes;
-            for (const BlendShape* blendShape : mesh.GetBlendShapes()) {
-                for (const BlendShapeChannel* blendShapeChannel : blendShape->BlendShapeChannels()) {
-                    const std::vector<const ShapeGeometry*>& shapeGeometries = blendShapeChannel->GetShapeGeometries();
-                    for (size_t i = 0; i < shapeGeometries.size(); i++) {
-                        aiAnimMesh *animMesh = aiCreateAnimMesh(out_mesh);
-                        const ShapeGeometry* shapeGeometry = shapeGeometries.at(i);
-                        const std::vector<aiVector3D>& vertices = shapeGeometry->GetVertices();
-                        const std::vector<aiVector3D>& normals = shapeGeometry->GetNormals();
-                        const std::vector<unsigned int>& indices = shapeGeometry->GetIndices();
-                        animMesh->mName.Set(FixAnimMeshName(shapeGeometry->Name()));
-                        for (size_t j = 0; j < indices.size(); j++) {
-                            unsigned int index = indices.at(j);
-                            aiVector3D vertex = vertices.at(j);
-                            aiVector3D normal = normals.at(j);
-                            unsigned int count = 0;
-                            const unsigned int* outIndices = mesh.ToOutputVertexIndex(index, count);
-                            for (unsigned int k = 0; k < count; k++) {
-                                unsigned int index = outIndices[k];
-                                animMesh->mVertices[index] += vertex;
-                                if (animMesh->mNormals != nullptr) {
-                                    animMesh->mNormals[index] += normal;
-                                    animMesh->mNormals[index].NormalizeSafe();
-                                }
-                            }
-                        }
-                        animMesh->mWeight = shapeGeometries.size() > 1 ? blendShapeChannel->DeformPercent() / 100.0f : 1.0f;
-                        animMeshes.push_back(animMesh);
-                    }
-                }
-            }
-            const size_t numAnimMeshes = animMeshes.size();
-            if (numAnimMeshes > 0) {
-                out_mesh->mNumAnimMeshes = static_cast<unsigned int>(numAnimMeshes);
-                out_mesh->mAnimMeshes = new aiAnimMesh*[numAnimMeshes];
-                for (size_t i = 0; i < numAnimMeshes; i++) {
-                    out_mesh->mAnimMeshes[i] = animMeshes.at(i);
-                }
-            }
-            return static_cast<unsigned int>(meshes.size() - 1);
-        }
-
-        std::vector<unsigned int>
-        FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, aiNode *parent,
-                                               aiNode *root_node,
-                                               const aiMatrix4x4 &absolute_transform)
-        {
-            const MatIndexArray& mindices = mesh.GetMaterialIndices();
-            ai_assert(mindices.size());
-
-            std::set<MatIndexArray::value_type> had;
-            std::vector<unsigned int> indices;
-
-            for (MatIndexArray::value_type index : mindices) {
-                if (had.find(index) == had.end()) {
-
-                    indices.push_back(ConvertMeshMultiMaterial(mesh, model, index, parent, root_node, absolute_transform));
-                    had.insert(index);
-                }
-            }
-
-            return indices;
-        }
-
-        unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model,
-                                                            MatIndexArray::value_type index,
-                                                            aiNode *parent, aiNode *root_node,
-                                                            const aiMatrix4x4 &absolute_transform)
-        {
-            aiMesh* const out_mesh = SetupEmptyMesh(mesh, parent);
-
-            const MatIndexArray& mindices = mesh.GetMaterialIndices();
-            const std::vector<aiVector3D>& vertices = mesh.GetVertices();
-            const std::vector<unsigned int>& faces = mesh.GetFaceIndexCounts();
-
-            const bool process_weights = doc.Settings().readWeights && mesh.DeformerSkin() != nullptr;
-
-            unsigned int count_faces = 0;
-            unsigned int count_vertices = 0;
-
-            // count faces
-            std::vector<unsigned int>::const_iterator itf = faces.begin();
-            for (MatIndexArray::const_iterator it = mindices.begin(),
-                end = mindices.end(); it != end; ++it, ++itf)
-            {
-                if ((*it) != index) {
-                    continue;
-                }
-                ++count_faces;
-                count_vertices += *itf;
-            }
-
-            ai_assert(count_faces);
-            ai_assert(count_vertices);
-
-            // mapping from output indices to DOM indexing, needed to resolve weights or blendshapes
-            std::vector<unsigned int> reverseMapping;
-            std::map<unsigned int, unsigned int> translateIndexMap;
-            if (process_weights || mesh.GetBlendShapes().size() > 0) {
-                reverseMapping.resize(count_vertices);
-            }
-
-            // allocate output data arrays, but don't fill them yet
-            out_mesh->mNumVertices = count_vertices;
-            out_mesh->mVertices = new aiVector3D[count_vertices];
-
-            out_mesh->mNumFaces = count_faces;
-            aiFace* fac = out_mesh->mFaces = new aiFace[count_faces]();
-
-
-            // allocate normals
-            const std::vector<aiVector3D>& normals = mesh.GetNormals();
-            if (normals.size()) {
-                ai_assert(normals.size() == vertices.size());
-                out_mesh->mNormals = new aiVector3D[vertices.size()];
-            }
-
-            // allocate tangents, binormals.
-            const std::vector<aiVector3D>& tangents = mesh.GetTangents();
-            const std::vector<aiVector3D>* binormals = &mesh.GetBinormals();
-            std::vector<aiVector3D> tempBinormals;
-
-            if (tangents.size()) {
-                if (!binormals->size()) {
-                    if (normals.size()) {
-                        // XXX this computes the binormals for the entire mesh, not only
-                        // the part for which we need them.
-                        tempBinormals.resize(normals.size());
-                        for (unsigned int i = 0; i < tangents.size(); ++i) {
-                            tempBinormals[i] = normals[i] ^ tangents[i];
-                        }
-
-                        binormals = &tempBinormals;
-                    }
-                    else {
-                        binormals = nullptr;
-                    }
-                }
-
-                if (binormals) {
-                    ai_assert(tangents.size() == vertices.size() && binormals->size() == vertices.size());
-
-                    out_mesh->mTangents = new aiVector3D[vertices.size()];
-                    out_mesh->mBitangents = new aiVector3D[vertices.size()];
-                }
-            }
-
-            // allocate texture coords
-            unsigned int num_uvs = 0;
-            for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i, ++num_uvs) {
-                const std::vector<aiVector2D>& uvs = mesh.GetTextureCoords(i);
-                if (uvs.empty()) {
-                    break;
-                }
-
-                out_mesh->mTextureCoords[i] = new aiVector3D[vertices.size()];
-                out_mesh->mNumUVComponents[i] = 2;
-            }
-
-            // allocate vertex colors
-            unsigned int num_vcs = 0;
-            for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i, ++num_vcs) {
-                const std::vector<aiColor4D>& colors = mesh.GetVertexColors(i);
-                if (colors.empty()) {
-                    break;
-                }
-
-                out_mesh->mColors[i] = new aiColor4D[vertices.size()];
-            }
-
-            unsigned int cursor = 0, in_cursor = 0;
-
-            itf = faces.begin();
-            for (MatIndexArray::const_iterator it = mindices.begin(), end = mindices.end(); it != end; ++it, ++itf)
-            {
-                const unsigned int pcount = *itf;
-                if ((*it) != index) {
-                    in_cursor += pcount;
-                    continue;
-                }
-
-                aiFace& f = *fac++;
-
-                f.mNumIndices = pcount;
-                f.mIndices = new unsigned int[pcount];
-                switch (pcount)
-                {
-                case 1:
-                    out_mesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
-                    break;
-                case 2:
-                    out_mesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
-                    break;
-                case 3:
-                    out_mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
-                    break;
-                default:
-                    out_mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
-                    break;
-                }
-                for (unsigned int i = 0; i < pcount; ++i, ++cursor, ++in_cursor) {
-                    f.mIndices[i] = cursor;
-
-                    if (reverseMapping.size()) {
-                        reverseMapping[cursor] = in_cursor;
-                        translateIndexMap[in_cursor] = cursor;
-                    }
-
-                    out_mesh->mVertices[cursor] = vertices[in_cursor];
-
-                    if (out_mesh->mNormals) {
-                        out_mesh->mNormals[cursor] = normals[in_cursor];
-                    }
-
-                    if (out_mesh->mTangents) {
-                        out_mesh->mTangents[cursor] = tangents[in_cursor];
-                        out_mesh->mBitangents[cursor] = (*binormals)[in_cursor];
-                    }
-
-                    for (unsigned int j = 0; j < num_uvs; ++j) {
-                        const std::vector<aiVector2D>& uvs = mesh.GetTextureCoords(j);
-                        out_mesh->mTextureCoords[j][cursor] = aiVector3D(uvs[in_cursor].x, uvs[in_cursor].y, 0.0f);
-                    }
-
-                    for (unsigned int j = 0; j < num_vcs; ++j) {
-                        const std::vector<aiColor4D>& cols = mesh.GetVertexColors(j);
-                        out_mesh->mColors[j][cursor] = cols[in_cursor];
-                    }
-                }
-            }
-
-            ConvertMaterialForMesh(out_mesh, model, mesh, index);
-
-            if (process_weights) {
-                ConvertWeights(out_mesh, model, mesh, absolute_transform, parent, root_node, index, &reverseMapping);
-            }
-
-            std::vector<aiAnimMesh*> animMeshes;
-            for (const BlendShape* blendShape : mesh.GetBlendShapes()) {
-                for (const BlendShapeChannel* blendShapeChannel : blendShape->BlendShapeChannels()) {
-                    const std::vector<const ShapeGeometry*>& shapeGeometries = blendShapeChannel->GetShapeGeometries();
-                    for (size_t i = 0; i < shapeGeometries.size(); i++) {
-                        aiAnimMesh* animMesh = aiCreateAnimMesh(out_mesh);
-                        const ShapeGeometry* shapeGeometry = shapeGeometries.at(i);
-                        const std::vector<aiVector3D>& vertices = shapeGeometry->GetVertices();
-                        const std::vector<aiVector3D>& normals = shapeGeometry->GetNormals();
-                        const std::vector<unsigned int>& indices = shapeGeometry->GetIndices();
-                        animMesh->mName.Set(FixAnimMeshName(shapeGeometry->Name()));
-                        for (size_t j = 0; j < indices.size(); j++) {
-                            unsigned int index = indices.at(j);
-                            aiVector3D vertex = vertices.at(j);
-                            aiVector3D normal = normals.at(j);
-                            unsigned int count = 0;
-                            const unsigned int* outIndices = mesh.ToOutputVertexIndex(index, count);
-                            for (unsigned int k = 0; k < count; k++) {
-                                unsigned int outIndex = outIndices[k];
-                                if (translateIndexMap.find(outIndex) == translateIndexMap.end())
-                                    continue;
-                                unsigned int index = translateIndexMap[outIndex];
-                                animMesh->mVertices[index] += vertex;
-                                if (animMesh->mNormals != nullptr) {
-                                    animMesh->mNormals[index] += normal;
-                                    animMesh->mNormals[index].NormalizeSafe();
-                                }
-                            }
-                        }
-                        animMesh->mWeight = shapeGeometries.size() > 1 ? blendShapeChannel->DeformPercent() / 100.0f : 1.0f;
-                        animMeshes.push_back(animMesh);
-                    }
-                }
-            }
-
-            const size_t numAnimMeshes = animMeshes.size();
-            if (numAnimMeshes > 0) {
-                out_mesh->mNumAnimMeshes = static_cast<unsigned int>(numAnimMeshes);
-                out_mesh->mAnimMeshes = new aiAnimMesh*[numAnimMeshes];
-                for (size_t i = 0; i < numAnimMeshes; i++) {
-                    out_mesh->mAnimMeshes[i] = animMeshes.at(i);
-                }
-            }
-
-            return static_cast<unsigned int>(meshes.size() - 1);
-        }
-
-        void FBXConverter::ConvertWeights(aiMesh *out, const Model &model, const MeshGeometry &geo,
-                                          const aiMatrix4x4 &absolute_transform,
-                                          aiNode *parent, aiNode *root_node, unsigned int materialIndex,
-                                          std::vector<unsigned int> *outputVertStartIndices)
-        {
-            ai_assert(geo.DeformerSkin());
-
-            std::vector<size_t> out_indices;
-            std::vector<size_t> index_out_indices;
-            std::vector<size_t> count_out_indices;
-
-            const Skin& sk = *geo.DeformerSkin();
-
-            std::vector<aiBone*> bones;
-
-            const bool no_mat_check = materialIndex == NO_MATERIAL_SEPARATION;
-            ai_assert(no_mat_check || outputVertStartIndices);
-
-            try {
-                // iterate over the sub deformers
-                for (const Cluster* cluster : sk.Clusters()) {
-                    ai_assert(cluster);
-
-                    const WeightIndexArray& indices = cluster->GetIndices();
-
-                    const MatIndexArray& mats = geo.GetMaterialIndices();
-
-                    const size_t no_index_sentinel = std::numeric_limits<size_t>::max();
-
-                    count_out_indices.clear();
-                    index_out_indices.clear();
-                    out_indices.clear();
-
-
-                    // now check if *any* of these weights is contained in the output mesh,
-                    // taking notes so we don't need to do it twice.
-                    for (WeightIndexArray::value_type index : indices) {
-
-                        unsigned int count = 0;
-                        const unsigned int* const out_idx = geo.ToOutputVertexIndex(index, count);
-                        // ToOutputVertexIndex only returns nullptr if index is out of bounds
-                        // which should never happen
-                        ai_assert(out_idx != nullptr);
-
-                        index_out_indices.push_back(no_index_sentinel);
-                        count_out_indices.push_back(0);
-
-                        for (unsigned int i = 0; i < count; ++i) {
-                            if (no_mat_check || static_cast<size_t>(mats[geo.FaceForVertexIndex(out_idx[i])]) == materialIndex) {
-
-                                if (index_out_indices.back() == no_index_sentinel) {
-                                    index_out_indices.back() = out_indices.size();
-                                }
-
-                                if (no_mat_check) {
-                                    out_indices.push_back(out_idx[i]);
-                                } else {
-                                    // this extra lookup is in O(logn), so the entire algorithm becomes O(nlogn)
-                                    const std::vector<unsigned int>::iterator it = std::lower_bound(
-                                        outputVertStartIndices->begin(),
-                                        outputVertStartIndices->end(),
-                                        out_idx[i]
-                                    );
-
-                                    out_indices.push_back(std::distance(outputVertStartIndices->begin(), it));
-                                }
-
-                                ++count_out_indices.back();                               
-                            }
-                        }
-                    }
-
-                    // if we found at least one, generate the output bones
-                    // XXX this could be heavily simplified by collecting the bone
-                    // data in a single step.
-                    ConvertCluster(bones, cluster, out_indices, index_out_indices,
-                                   count_out_indices, absolute_transform, parent, root_node);
-                }
-
-                bone_map.clear();
-            }
-            catch (std::exception&e) {
-                std::for_each(bones.begin(), bones.end(), Util::delete_fun<aiBone>());
-                throw;
-            }
-
-            if (bones.empty()) {
-                out->mBones = nullptr;
-                out->mNumBones = 0;
-                return;
-            } else {
-                out->mBones = new aiBone *[bones.size()]();
-                out->mNumBones = static_cast<unsigned int>(bones.size());
-
-                std::swap_ranges(bones.begin(), bones.end(), out->mBones);
-            }
-        }
-
-        const aiNode* FBXConverter::GetNodeByName( const aiString& name, aiNode *current_node )
-        {
-            aiNode * iter = current_node;
-            //printf("Child count: %d", iter->mNumChildren);
-            return iter;
-        }
-
-        void FBXConverter::ConvertCluster(std::vector<aiBone *> &local_mesh_bones, const Cluster *cl,
-                                          std::vector<size_t> &out_indices, std::vector<size_t> &index_out_indices,
-                                          std::vector<size_t> &count_out_indices, const aiMatrix4x4 &absolute_transform,
-                                          aiNode *parent, aiNode *root_node) {
-            ai_assert(cl); // make sure cluster valid
-            std::string deformer_name = cl->TargetNode()->Name();
-            aiString bone_name = aiString(FixNodeName(deformer_name));
-
-            aiBone *bone = nullptr;
-
-            if (bone_map.count(deformer_name)) {
-                std::cout << "retrieved bone from lookup " << bone_name.C_Str() << ". Deformer: " << deformer_name
-                          << std::endl;
-                bone = bone_map[deformer_name];
-            } else {
-                std::cout << "created new bone " << bone_name.C_Str() << ". Deformer: " << deformer_name << std::endl;
-                bone = new aiBone();
-                bone->mName = bone_name;
-
-                // store local transform link for post processing
-                bone->mOffsetMatrix = cl->TransformLink();
-                bone->mOffsetMatrix.Inverse();
-
-                aiMatrix4x4 matrix = (aiMatrix4x4)absolute_transform;
-
-                bone->mOffsetMatrix = bone->mOffsetMatrix * matrix; // * mesh_offset
-
-
-                //
-                // Now calculate the aiVertexWeights
-                //
-
-                aiVertexWeight *cursor = nullptr;
-
-                bone->mNumWeights = static_cast<unsigned int>(out_indices.size());
-                cursor = bone->mWeights = new aiVertexWeight[out_indices.size()];
-
-                const size_t no_index_sentinel = std::numeric_limits<size_t>::max();
-                const WeightArray& weights = cl->GetWeights();
-
-                const size_t c = index_out_indices.size();
-                for (size_t i = 0; i < c; ++i) {
-                    const size_t index_index = index_out_indices[i];
-
-                    if (index_index == no_index_sentinel) {
-                        continue;
-                    }
-
-                    const size_t cc = count_out_indices[i];
-                    for (size_t j = 0; j < cc; ++j) {
-                        // cursor runs from first element relative to the start
-                        // or relative to the start of the next indexes.
-                        aiVertexWeight& out_weight = *cursor++;
-
-                        out_weight.mVertexId = static_cast<unsigned int>(out_indices[index_index + j]);
-                        out_weight.mWeight = weights[i];
-                    }
-                }
-
-                bone_map.insert(std::pair<const std::string, aiBone *>(deformer_name, bone));
-            }
-
-            std::cout << "bone research: Indicies size: " << out_indices.size() << std::endl;
-
-            // lookup must be populated in case something goes wrong
-            // this also allocates bones to mesh instance outside
-            local_mesh_bones.push_back(bone);
-        }
-
-        void FBXConverter::ConvertMaterialForMesh(aiMesh* out, const Model& model, const MeshGeometry& geo,
-            MatIndexArray::value_type materialIndex)
-        {
-            // locate source materials for this mesh
-            const std::vector<const Material*>& mats = model.GetMaterials();
-            if (static_cast<unsigned int>(materialIndex) >= mats.size() || materialIndex < 0) {
-                FBXImporter::LogError("material index out of bounds, setting default material");
-                out->mMaterialIndex = GetDefaultMaterial();
-                return;
-            }
-
-            const Material* const mat = mats[materialIndex];
-            MaterialMap::const_iterator it = materials_converted.find(mat);
-            if (it != materials_converted.end()) {
-                out->mMaterialIndex = (*it).second;
-                return;
-            }
-
-            out->mMaterialIndex = ConvertMaterial(*mat, &geo);
-            materials_converted[mat] = out->mMaterialIndex;
-        }
-
-        unsigned int FBXConverter::GetDefaultMaterial()
-        {
-            if (defaultMaterialIndex) {
-                return defaultMaterialIndex - 1;
-            }
-
-            aiMaterial* out_mat = new aiMaterial();
-            materials.push_back(out_mat);
-
-            const aiColor3D diffuse = aiColor3D(0.8f, 0.8f, 0.8f);
-            out_mat->AddProperty(&diffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
-
-            aiString s;
-            s.Set(AI_DEFAULT_MATERIAL_NAME);
-
-            out_mat->AddProperty(&s, AI_MATKEY_NAME);
-
-            defaultMaterialIndex = static_cast<unsigned int>(materials.size());
-            return defaultMaterialIndex - 1;
-        }
-
-
-        unsigned int FBXConverter::ConvertMaterial(const Material& material, const MeshGeometry* const mesh)
-        {
-            const PropertyTable& props = material.Props();
-
-            // generate empty output material
-            aiMaterial* out_mat = new aiMaterial();
-            materials_converted[&material] = static_cast<unsigned int>(materials.size());
-
-            materials.push_back(out_mat);
-
-            aiString str;
-
-            // strip Material:: prefix
-            std::string name = material.Name();
-            if (name.substr(0, 10) == "Material::") {
-                name = name.substr(10);
-            }
-
-            // set material name if not empty - this could happen
-            // and there should be no key for it in this case.
-            if (name.length()) {
-                str.Set(name);
-                out_mat->AddProperty(&str, AI_MATKEY_NAME);
-            }
-
-            // Set the shading mode as best we can: The FBX specification only mentions Lambert and Phong, and only Phong is mentioned in Assimp's aiShadingMode enum.
-            if (material.GetShadingModel() == "phong")
-            {
-                aiShadingMode shadingMode = aiShadingMode_Phong;
-                out_mat->AddProperty<aiShadingMode>(&shadingMode, 1, AI_MATKEY_SHADING_MODEL);               
-            }
-
-            // shading stuff and colors
-            SetShadingPropertiesCommon(out_mat, props);
-            SetShadingPropertiesRaw( out_mat, props, material.Textures(), mesh );
-
-            // texture assignments
-            SetTextureProperties(out_mat, material.Textures(), mesh);
-            SetTextureProperties(out_mat, material.LayeredTextures(), mesh);
-
-            return static_cast<unsigned int>(materials.size() - 1);
-        }
-
-        unsigned int FBXConverter::ConvertVideo(const Video& video)
-        {
-            // generate empty output texture
-            aiTexture* out_tex = new aiTexture();
-            textures.push_back(out_tex);
-
-            // assuming the texture is compressed
-            out_tex->mWidth = static_cast<unsigned int>(video.ContentLength()); // total data size
-            out_tex->mHeight = 0; // fixed to 0
-
-            // steal the data from the Video to avoid an additional copy
-            out_tex->pcData = reinterpret_cast<aiTexel*>(const_cast<Video&>(video).RelinquishContent());
-
-            // try to extract a hint from the file extension
-            const std::string& filename = video.RelativeFilename().empty() ? video.FileName() : video.RelativeFilename();
-            std::string ext = BaseImporter::GetExtension(filename);
-
-            if (ext == "jpeg") {
-                ext = "jpg";
-            }
-
-            if (ext.size() <= 3) {
-                memcpy(out_tex->achFormatHint, ext.c_str(), ext.size());
-            }
-
-            out_tex->mFilename.Set(filename.c_str());
-
-            return static_cast<unsigned int>(textures.size() - 1);
-        }
-
-        aiString FBXConverter::GetTexturePath(const Texture* tex)
-        {
-            aiString path;
-            path.Set(tex->RelativeFilename());
-
-            const Video* media = tex->Media();
-            if (media != nullptr) {
-                bool textureReady = false; //tells if our texture is ready (if it was loaded or if it was found)
-                unsigned int index;
-
-                VideoMap::const_iterator it = textures_converted.find(*media);
-                if (it != textures_converted.end()) {
-                    index = (*it).second;
-                    textureReady = true;
-                }
-                else {
-                    if (media->ContentLength() > 0) {
-                        index = ConvertVideo(*media);
-                        textures_converted[*media] = index;
-                        textureReady = true;
-                    }
-                }
-
-                // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture), if the texture is ready
-                if (doc.Settings().useLegacyEmbeddedTextureNaming) {
-                    if (textureReady) {
-                        // TODO: check the possibility of using the flag "AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING"
-                        // In FBX files textures are now stored internally by Assimp with their filename included
-                        // Now Assimp can lookup through the loaded textures after all data is processed
-                        // We need to load all textures before referencing them, as FBX file format order may reference a texture before loading it
-                        // This may occur on this case too, it has to be studied
-                        path.data[0] = '*';
-                        path.length = 1 + ASSIMP_itoa10(path.data + 1, MAXLEN - 1, index);
-                    }
-                }
-            }
-
-            return path;
-        }
-
-        void FBXConverter::TrySetTextureProperties(aiMaterial* out_mat, const TextureMap& textures,
-                const std::string& propName,
-                aiTextureType target, const MeshGeometry* const mesh) {
-            TextureMap::const_iterator it = textures.find(propName);
-            if (it == textures.end()) {
-                return;
-            }
-
-            const Texture* const tex = (*it).second;
-            if (tex != 0)
-            {
-                aiString path = GetTexturePath(tex);
-                out_mat->AddProperty(&path, _AI_MATKEY_TEXTURE_BASE, target, 0);
-
-                aiUVTransform uvTrafo;
-                // XXX handle all kinds of UV transformations
-                uvTrafo.mScaling = tex->UVScaling();
-                uvTrafo.mTranslation = tex->UVTranslation();
-                out_mat->AddProperty(&uvTrafo, 1, _AI_MATKEY_UVTRANSFORM_BASE, target, 0);
-
-                const PropertyTable& props = tex->Props();
-
-                int uvIndex = 0;
-
-                bool ok;
-                const std::string& uvSet = PropertyGet<std::string>(props, "UVSet", ok);
-                if (ok) {
-                    // "default" is the name which usually appears in the FbxFileTexture template
-                    if (uvSet != "default" && uvSet.length()) {
-                        // this is a bit awkward - we need to find a mesh that uses this
-                        // material and scan its UV channels for the given UV name because
-                        // assimp references UV channels by index, not by name.
-
-                        // XXX: the case that UV channels may appear in different orders
-                        // in meshes is unhandled. A possible solution would be to sort
-                        // the UV channels alphabetically, but this would have the side
-                        // effect that the primary (first) UV channel would sometimes
-                        // be moved, causing trouble when users read only the first
-                        // UV channel and ignore UV channel assignments altogether.
-
-                        const unsigned int matIndex = static_cast<unsigned int>(std::distance(materials.begin(),
-                            std::find(materials.begin(), materials.end(), out_mat)
-                        ));
-
-
-                        uvIndex = -1;
-                        if (!mesh)
-                        {
-                            for (const MeshMap::value_type& v : meshes_converted) {
-                                const MeshGeometry* const meshGeom = dynamic_cast<const MeshGeometry*> (v.first);
-                                if (!meshGeom) {
-                                    continue;
-                                }
-
-                                const MatIndexArray& mats = meshGeom->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 (meshGeom->GetTextureCoords(i).empty()) {
-                                        break;
-                                    }
-                                    const std::string& name = meshGeom->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()) {
-                                    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");
-                            }
-
-                            if (uvIndex == -1) {
-                                uvIndex = index;
-                            }
-                        }
-
-                        if (uvIndex == -1) {
-                            FBXImporter::LogWarn("failed to resolve UV channel " + uvSet + ", using first UV channel");
-                            uvIndex = 0;
-                        }
-                    }
-                }
-
-                out_mat->AddProperty(&uvIndex, 1, _AI_MATKEY_UVWSRC_BASE, target, 0);
-            }
-        }
-
-        void FBXConverter::TrySetTextureProperties(aiMaterial* out_mat, const LayeredTextureMap& layeredTextures,
-            const std::string& propName,
-            aiTextureType target, const MeshGeometry* const mesh) {
-            LayeredTextureMap::const_iterator it = layeredTextures.find(propName);
-            if (it == layeredTextures.end()) {
-                return;
-            }
-
-            int texCount = (*it).second->textureCount();
-
-            // Set the blend mode for layered textures
-            int blendmode = (*it).second->GetBlendMode();
-            out_mat->AddProperty(&blendmode, 1, _AI_MATKEY_TEXOP_BASE, target, 0);
-
-            for (int texIndex = 0; texIndex < texCount; texIndex++) {
-
-                const Texture* const tex = (*it).second->getTexture(texIndex);
-
-                aiString path = GetTexturePath(tex);
-                out_mat->AddProperty(&path, _AI_MATKEY_TEXTURE_BASE, target, texIndex);
-
-                aiUVTransform uvTrafo;
-                // XXX handle all kinds of UV transformations
-                uvTrafo.mScaling = tex->UVScaling();
-                uvTrafo.mTranslation = tex->UVTranslation();
-                out_mat->AddProperty(&uvTrafo, 1, _AI_MATKEY_UVTRANSFORM_BASE, target, texIndex);
-
-                const PropertyTable& props = tex->Props();
-
-                int uvIndex = 0;
-
-                bool ok;
-                const std::string& uvSet = PropertyGet<std::string>(props, "UVSet", ok);
-                if (ok) {
-                    // "default" is the name which usually appears in the FbxFileTexture template
-                    if (uvSet != "default" && uvSet.length()) {
-                        // this is a bit awkward - we need to find a mesh that uses this
-                        // material and scan its UV channels for the given UV name because
-                        // assimp references UV channels by index, not by name.
-
-                        // XXX: the case that UV channels may appear in different orders
-                        // in meshes is unhandled. A possible solution would be to sort
-                        // the UV channels alphabetically, but this would have the side
-                        // effect that the primary (first) UV channel would sometimes
-                        // be moved, causing trouble when users read only the first
-                        // UV channel and ignore UV channel assignments altogether.
-
-                        const unsigned int matIndex = static_cast<unsigned int>(std::distance(materials.begin(),
-                            std::find(materials.begin(), materials.end(), out_mat)
-                        ));
-
-                        uvIndex = -1;
-                        if (!mesh)
-                        {
-                            for (const MeshMap::value_type& v : meshes_converted) {
-                                const MeshGeometry* const meshGeom = dynamic_cast<const MeshGeometry*> (v.first);
-                                if (!meshGeom) {
-                                    continue;
-                                }
-
-                                const MatIndexArray& mats = meshGeom->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 (meshGeom->GetTextureCoords(i).empty()) {
-                                        break;
-                                    }
-                                    const std::string& name = meshGeom->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()) {
-                                    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");
-                            }
-
-                            if (uvIndex == -1) {
-                                uvIndex = index;
-                            }
-                        }
-
-                        if (uvIndex == -1) {
-                            FBXImporter::LogWarn("failed to resolve UV channel " + uvSet + ", using first UV channel");
-                            uvIndex = 0;
-                        }
-                    }
-                }
-
-                out_mat->AddProperty(&uvIndex, 1, _AI_MATKEY_UVWSRC_BASE, target, texIndex);
-            }
-        }
-
-        void FBXConverter::SetTextureProperties(aiMaterial* out_mat, const TextureMap& textures, const MeshGeometry* const mesh)
-        {
-            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, "SpecularFactor", 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);
-			TrySetTextureProperties( out_mat, textures, "TransparencyFactor", aiTextureType_OPACITY, mesh );
-			TrySetTextureProperties( out_mat, textures, "EmissiveFactor", aiTextureType_EMISSIVE, mesh );
-            //Maya counterparts
-            TrySetTextureProperties(out_mat, textures, "Maya|DiffuseTexture", aiTextureType_DIFFUSE, mesh);
-            TrySetTextureProperties(out_mat, textures, "Maya|NormalTexture", aiTextureType_NORMALS, mesh);
-            TrySetTextureProperties(out_mat, textures, "Maya|SpecularTexture", aiTextureType_SPECULAR, mesh);
-            TrySetTextureProperties(out_mat, textures, "Maya|FalloffTexture", aiTextureType_OPACITY, mesh);
-            TrySetTextureProperties(out_mat, textures, "Maya|ReflectionMapTexture", aiTextureType_REFLECTION, mesh);
-            
-            // Maya PBR
-            TrySetTextureProperties(out_mat, textures, "Maya|baseColor|file", aiTextureType_BASE_COLOR, mesh);
-            TrySetTextureProperties(out_mat, textures, "Maya|normalCamera|file", aiTextureType_NORMAL_CAMERA, mesh);
-            TrySetTextureProperties(out_mat, textures, "Maya|emissionColor|file", aiTextureType_EMISSION_COLOR, mesh);
-            TrySetTextureProperties(out_mat, textures, "Maya|metalness|file", aiTextureType_METALNESS, mesh);
-            TrySetTextureProperties(out_mat, textures, "Maya|diffuseRoughness|file", aiTextureType_DIFFUSE_ROUGHNESS, mesh);
-            
-            // Maya stingray
-            TrySetTextureProperties(out_mat, textures, "Maya|TEX_color_map|file", aiTextureType_BASE_COLOR, mesh);
-            TrySetTextureProperties(out_mat, textures, "Maya|TEX_normal_map|file", aiTextureType_NORMAL_CAMERA, mesh);
-            TrySetTextureProperties(out_mat, textures, "Maya|TEX_emissive_map|file", aiTextureType_EMISSION_COLOR, mesh);
-            TrySetTextureProperties(out_mat, textures, "Maya|TEX_metallic_map|file", aiTextureType_METALNESS, mesh);
-            TrySetTextureProperties(out_mat, textures, "Maya|TEX_roughness_map|file", aiTextureType_DIFFUSE_ROUGHNESS, mesh);
-            TrySetTextureProperties(out_mat, textures, "Maya|TEX_ao_map|file", aiTextureType_AMBIENT_OCCLUSION, mesh);            
-        }
-
-        void FBXConverter::SetTextureProperties(aiMaterial* out_mat, const LayeredTextureMap& layeredTextures, const MeshGeometry* const mesh)
-        {
-            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, "SpecularFactor", 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);
-			TrySetTextureProperties( out_mat, layeredTextures, "EmissiveFactor", aiTextureType_EMISSIVE, mesh );
-			TrySetTextureProperties( out_mat, layeredTextures, "TransparencyFactor", aiTextureType_OPACITY, mesh );
-        }
-
-        aiColor3D FBXConverter::GetColorPropertyFactored(const PropertyTable& props, const std::string& colorName,
-            const std::string& factorName, bool& result, bool useTemplate)
-        {
-            result = true;
-
-            bool ok;
-            aiVector3D BaseColor = PropertyGet<aiVector3D>(props, colorName, ok, useTemplate);
-            if (!ok) {
-                result = false;
-                return aiColor3D(0.0f, 0.0f, 0.0f);
-            }
-
-            // if no factor name, return the colour as is
-            if (factorName.empty()) {
-                return aiColor3D(BaseColor.x, BaseColor.y, BaseColor.z);
-            }
-
-            // otherwise it should be multiplied by the factor, if found.
-            float factor = PropertyGet<float>(props, factorName, ok, useTemplate);
-            if (ok) {
-                BaseColor *= factor;
-            }
-            return aiColor3D(BaseColor.x, BaseColor.y, BaseColor.z);
-        }
-
-        aiColor3D FBXConverter::GetColorPropertyFromMaterial(const PropertyTable& props, const std::string& baseName,
-            bool& result)
-        {
-            return GetColorPropertyFactored(props, baseName + "Color", baseName + "Factor", result, true);
-        }
-
-        aiColor3D FBXConverter::GetColorProperty(const PropertyTable& props, const std::string& colorName,
-            bool& result, bool useTemplate)
-        {
-            result = true;
-            bool ok;
-            const aiVector3D& ColorVec = PropertyGet<aiVector3D>(props, colorName, ok, useTemplate);
-            if (!ok) {
-                result = false;
-                return aiColor3D(0.0f, 0.0f, 0.0f);
-            }
-            return aiColor3D(ColorVec.x, ColorVec.y, ColorVec.z);
-        }
-
-        void FBXConverter::SetShadingPropertiesCommon(aiMaterial* out_mat, const PropertyTable& props)
-        {
-            // Set shading properties.
-            // Modern FBX Files have two separate systems for defining these,
-            // with only the more comprehensive one described in the property template.
-            // Likely the other values are a legacy system,
-            // which is still always exported by the official FBX SDK.
-            //
-            // Blender's FBX import and export mostly ignore this legacy system,
-            // and as we only support recent versions of FBX anyway, we can do the same.
-            bool ok;
-
-            const aiColor3D& Diffuse = GetColorPropertyFromMaterial(props, "Diffuse", ok);
-            if (ok) {
-                out_mat->AddProperty(&Diffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
-            }
-
-            const aiColor3D& Emissive = GetColorPropertyFromMaterial(props, "Emissive", ok);
-            if (ok) {
-                out_mat->AddProperty(&Emissive, 1, AI_MATKEY_COLOR_EMISSIVE);
-            }
-
-            const aiColor3D& Ambient = GetColorPropertyFromMaterial(props, "Ambient", ok);
-            if (ok) {
-                out_mat->AddProperty(&Ambient, 1, AI_MATKEY_COLOR_AMBIENT);
-            }
-
-            // we store specular factor as SHININESS_STRENGTH, so just get the color
-            const aiColor3D& Specular = GetColorProperty(props, "SpecularColor", ok, true);
-            if (ok) {
-                out_mat->AddProperty(&Specular, 1, AI_MATKEY_COLOR_SPECULAR);
-            }
-
-            // and also try to get SHININESS_STRENGTH
-            const float SpecularFactor = PropertyGet<float>(props, "SpecularFactor", ok, true);
-            if (ok) {
-                out_mat->AddProperty(&SpecularFactor, 1, AI_MATKEY_SHININESS_STRENGTH);
-            }
-
-            // and the specular exponent
-            const float ShininessExponent = PropertyGet<float>(props, "ShininessExponent", ok);
-            if (ok) {
-                out_mat->AddProperty(&ShininessExponent, 1, AI_MATKEY_SHININESS);
-            }
-
-            // TransparentColor / TransparencyFactor... gee thanks FBX :rolleyes:
-            const aiColor3D& Transparent = GetColorPropertyFactored(props, "TransparentColor", "TransparencyFactor", ok);
-            float CalculatedOpacity = 1.0f;
-            if (ok) {
-                out_mat->AddProperty(&Transparent, 1, AI_MATKEY_COLOR_TRANSPARENT);
-                // as calculated by FBX SDK 2017:
-                CalculatedOpacity = 1.0f - ((Transparent.r + Transparent.g + Transparent.b) / 3.0f);
-            }
-
-            // try to get the transparency factor
-            const float TransparencyFactor = PropertyGet<float>(props, "TransparencyFactor", ok);
-            if (ok) {
-                out_mat->AddProperty(&TransparencyFactor, 1, AI_MATKEY_TRANSPARENCYFACTOR);
-            }
-
-            // use of TransparencyFactor is inconsistent.
-            // Maya always stores it as 1.0,
-            // so we can't use it to set AI_MATKEY_OPACITY.
-            // Blender is more sensible and stores it as the alpha value.
-            // However both the FBX SDK and Blender always write an additional
-            // legacy "Opacity" field, so we can try to use that.
-            //
-            // If we can't find it,
-            // we can fall back to the value which the FBX SDK calculates
-            // from transparency colour (RGB) and factor (F) as
-            // 1.0 - F*((R+G+B)/3).
-            //
-            // There's no consistent way to interpret this opacity value,
-            // so it's up to clients to do the correct thing.
-            const float Opacity = PropertyGet<float>(props, "Opacity", ok);
-            if (ok) {
-                out_mat->AddProperty(&Opacity, 1, AI_MATKEY_OPACITY);
-            }
-            else if (CalculatedOpacity != 1.0) {
-                out_mat->AddProperty(&CalculatedOpacity, 1, AI_MATKEY_OPACITY);
-            }
-
-            // reflection color and factor are stored separately
-            const aiColor3D& Reflection = GetColorProperty(props, "ReflectionColor", ok, true);
-            if (ok) {
-                out_mat->AddProperty(&Reflection, 1, AI_MATKEY_COLOR_REFLECTIVE);
-            }
-
-            float ReflectionFactor = PropertyGet<float>(props, "ReflectionFactor", ok, true);
-            if (ok) {
-                out_mat->AddProperty(&ReflectionFactor, 1, AI_MATKEY_REFLECTIVITY);
-            }
-
-            const float BumpFactor = PropertyGet<float>(props, "BumpFactor", ok);
-            if (ok) {
-                out_mat->AddProperty(&BumpFactor, 1, AI_MATKEY_BUMPSCALING);
-            }
-
-            const float DispFactor = PropertyGet<float>(props, "DisplacementFactor", ok);
-            if (ok) {
-                out_mat->AddProperty(&DispFactor, 1, "$mat.displacementscaling", 0, 0);
-    }
-}
-
-
-void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTable& props, const TextureMap& textures, const MeshGeometry* const mesh)
-{
-    // Add all the unparsed properties with a "$raw." prefix
-
-    const std::string prefix = "$raw.";
-
-    for (const DirectPropertyMap::value_type& prop : props.GetUnparsedProperties()) {
-
-        std::string name = prefix + prop.first;
-
-        if (const TypedProperty<aiVector3D>* interpreted = prop.second->As<TypedProperty<aiVector3D> >())
-        {
-            out_mat->AddProperty(&interpreted->Value(), 1, name.c_str(), 0, 0);
-        }
-        else if (const TypedProperty<aiColor3D>* interpreted = prop.second->As<TypedProperty<aiColor3D> >())
-        {
-            out_mat->AddProperty(&interpreted->Value(), 1, name.c_str(), 0, 0);
-        }
-        else if (const TypedProperty<aiColor4D>* interpreted = prop.second->As<TypedProperty<aiColor4D> >())
-        {
-            out_mat->AddProperty(&interpreted->Value(), 1, name.c_str(), 0, 0);
-        }
-        else if (const TypedProperty<float>* interpreted = prop.second->As<TypedProperty<float> >())
-        {
-            out_mat->AddProperty(&interpreted->Value(), 1, name.c_str(), 0, 0);
-        }
-        else if (const TypedProperty<int>* interpreted = prop.second->As<TypedProperty<int> >())
-        {
-            out_mat->AddProperty(&interpreted->Value(), 1, name.c_str(), 0, 0);
-        }
-        else if (const TypedProperty<bool>* interpreted = prop.second->As<TypedProperty<bool> >())
-        {
-            int value = interpreted->Value() ? 1 : 0;
-            out_mat->AddProperty(&value, 1, name.c_str(), 0, 0);
-        }
-        else if (const TypedProperty<std::string>* interpreted = prop.second->As<TypedProperty<std::string> >())
-        {
-            const aiString value = aiString(interpreted->Value());
-            out_mat->AddProperty(&value, name.c_str(), 0, 0);
-        }
-    }
-
-    // Add the textures' properties
-
-    for (TextureMap::const_iterator it = textures.begin(); it != textures.end(); it++) {
-
-        std::string name = prefix + it->first;
-
-        const Texture* const tex = (*it).second;
-        if (tex != nullptr)
-        {
-            aiString path;
-            path.Set(tex->RelativeFilename());
-
-            const Video* media = tex->Media();
-            if (media != nullptr && media->ContentLength() > 0) {
-                unsigned int index;
-
-                VideoMap::const_iterator it = textures_converted.find(*media);
-                if (it != textures_converted.end()) {
-                    index = (*it).second;
-                }
-                else {
-                    index = ConvertVideo(*media);
-                    textures_converted[*media] = index;
-                }
-
-                // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture)
-                path.data[0] = '*';
-                path.length = 1 + ASSIMP_itoa10(path.data + 1, MAXLEN - 1, index);
-            }
-
-            out_mat->AddProperty(&path, (name + "|file").c_str(), aiTextureType_UNKNOWN, 0);
-
-            aiUVTransform uvTrafo;
-            // XXX handle all kinds of UV transformations
-            uvTrafo.mScaling = tex->UVScaling();
-            uvTrafo.mTranslation = tex->UVTranslation();
-            out_mat->AddProperty(&uvTrafo, 1, (name + "|uvtrafo").c_str(), aiTextureType_UNKNOWN, 0);
- 
-            int uvIndex = 0;
-
-            bool uvFound = false;
-            const std::string& uvSet = PropertyGet<std::string>(tex->Props(), "UVSet", uvFound);
-            if (uvFound) {
-                // "default" is the name which usually appears in the FbxFileTexture template
-                if (uvSet != "default" && uvSet.length()) {
-                    // this is a bit awkward - we need to find a mesh that uses this
-                    // material and scan its UV channels for the given UV name because
-                    // assimp references UV channels by index, not by name.
-
-                    // XXX: the case that UV channels may appear in different orders
-                    // in meshes is unhandled. A possible solution would be to sort
-                    // the UV channels alphabetically, but this would have the side
-                    // effect that the primary (first) UV channel would sometimes
-                    // be moved, causing trouble when users read only the first
-                    // UV channel and ignore UV channel assignments altogether.
-
-                    std::vector<aiMaterial*>::iterator materialIt = std::find(materials.begin(), materials.end(), out_mat);
-                    const unsigned int matIndex = static_cast<unsigned int>(std::distance(materials.begin(), materialIt));
-
-                    uvIndex = -1;
-                    if (!mesh)
-                    {
-                        for (const MeshMap::value_type& v : meshes_converted) {
-                            const MeshGeometry* const meshGeom = dynamic_cast<const MeshGeometry*>(v.first);
-                            if (!meshGeom) {
-                                continue;
-                            }
-
-                            const MatIndexArray& mats = meshGeom->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 (meshGeom->GetTextureCoords(i).empty()) {
-                                    break;
-                                }
-                                const std::string& name = meshGeom->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()) {
-                                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");
-                        }
-
-                        if (uvIndex == -1) {
-                            uvIndex = index;
-                        }
-                    }
-
-                    if (uvIndex == -1) {
-                        FBXImporter::LogWarn("failed to resolve UV channel " + uvSet + ", using first UV channel");
-                        uvIndex = 0;
-                    }
-                }
-            }
-
-            out_mat->AddProperty(&uvIndex, 1, (name + "|uvwsrc").c_str(), aiTextureType_UNKNOWN, 0);
-        }
-            }
-        }
-
-
-        double FBXConverter::FrameRateToDouble(FileGlobalSettings::FrameRate fp, double customFPSVal) {
-            switch (fp) {
-            case FileGlobalSettings::FrameRate_DEFAULT:
-                return 1.0;
-
-            case FileGlobalSettings::FrameRate_120:
-                return 120.0;
-
-            case FileGlobalSettings::FrameRate_100:
-                return 100.0;
-
-            case FileGlobalSettings::FrameRate_60:
-                return 60.0;
-
-            case FileGlobalSettings::FrameRate_50:
-                return 50.0;
-
-            case FileGlobalSettings::FrameRate_48:
-                return 48.0;
-
-            case FileGlobalSettings::FrameRate_30:
-            case FileGlobalSettings::FrameRate_30_DROP:
-                return 30.0;
-
-            case FileGlobalSettings::FrameRate_NTSC_DROP_FRAME:
-            case FileGlobalSettings::FrameRate_NTSC_FULL_FRAME:
-                return 29.9700262;
-
-            case FileGlobalSettings::FrameRate_PAL:
-                return 25.0;
-
-            case FileGlobalSettings::FrameRate_CINEMA:
-                return 24.0;
-
-            case FileGlobalSettings::FrameRate_1000:
-                return 1000.0;
-
-            case FileGlobalSettings::FrameRate_CINEMA_ND:
-                return 23.976;
-
-            case FileGlobalSettings::FrameRate_CUSTOM:
-                return customFPSVal;
-
-            case FileGlobalSettings::FrameRate_MAX: // this is to silence compiler warnings
-                break;
-            }
-
-            ai_assert(false);
-
-            return -1.0f;
-        }
-
-
-        void FBXConverter::ConvertAnimations()
-        {
-            // first of all determine framerate
-            const FileGlobalSettings::FrameRate fps = doc.GlobalSettings().TimeMode();
-            const float custom = doc.GlobalSettings().CustomFrameRate();
-            anim_fps = FrameRateToDouble(fps, custom);
-
-            const std::vector<const AnimationStack*>& animations = doc.AnimationStacks();
-            for (const AnimationStack* stack : animations) {
-                ConvertAnimationStack(*stack);
-            }
-        }
-
-        std::string FBXConverter::FixNodeName(const std::string& name) {
-            // strip Model:: prefix, avoiding ambiguities (i.e. don't strip if
-            // this causes ambiguities, well possible between empty identifiers,
-            // such as "Model::" and ""). Make sure the behaviour is consistent
-            // across multiple calls to FixNodeName().
-            if (name.substr(0, 7) == "Model::") {
-                std::string temp = name.substr(7);
-                return temp;
-            }
-
-            return name;
-        }
-
-        std::string FBXConverter::FixAnimMeshName(const std::string& name) {
-            if (name.length()) {
-                size_t indexOf = name.find_first_of("::");
-                if (indexOf != std::string::npos && indexOf < name.size() - 2) {
-                    return name.substr(indexOf + 2);
-                }
-            }
-            return name.length() ? name : "AnimMesh";
-        }
-
-        void FBXConverter::ConvertAnimationStack(const AnimationStack& st)
-        {
-            const AnimationLayerList& layers = st.Layers();
-            if (layers.empty()) {
-                return;
-            }
-
-            aiAnimation* const anim = new aiAnimation();
-            animations.push_back(anim);
-
-            // strip AnimationStack:: prefix
-            std::string name = st.Name();
-            if (name.substr(0, 16) == "AnimationStack::") {
-                name = name.substr(16);
-            }
-            else if (name.substr(0, 11) == "AnimStack::") {
-                name = name.substr(11);
-            }
-
-            anim->mName.Set(name);
-
-            // need to find all nodes for which we need to generate node animations -
-            // it may happen that we need to merge multiple layers, though.
-            NodeMap node_map;
-
-            // reverse mapping from curves to layers, much faster than querying
-            // the FBX DOM for it.
-            LayerMap layer_map;
-
-            const char* prop_whitelist[] = {
-                "Lcl Scaling",
-                "Lcl Rotation",
-                "Lcl Translation",
-                "DeformPercent"
-            };
-
-            std::map<std::string, morphAnimData*> morphAnimDatas;
-
-            for (const AnimationLayer* layer : layers) {
-                ai_assert(layer);
-                const AnimationCurveNodeList& nodes = layer->Nodes(prop_whitelist, 4);
-                for (const AnimationCurveNode* node : nodes) {
-                    ai_assert(node);
-                    const Model* const model = dynamic_cast<const Model*>(node->Target());
-                    if (model) {
-                        const std::string& name = FixNodeName(model->Name());
-                        node_map[name].push_back(node);
-                        layer_map[node] = layer;
-                        continue;
-                    }
-                    const BlendShapeChannel* const bsc = dynamic_cast<const BlendShapeChannel*>(node->Target());
-                    if (bsc) {
-                        ProcessMorphAnimDatas(&morphAnimDatas, bsc, node);
-                    }
-                }
-            }
-
-            // generate node animations
-            std::vector<aiNodeAnim*> node_anims;
-
-            double min_time = 1e10;
-            double max_time = -1e10;
-
-            int64_t start_time = st.LocalStart();
-            int64_t stop_time = st.LocalStop();
-            bool has_local_startstop = start_time != 0 || stop_time != 0;
-            if (!has_local_startstop) {
-                // no time range given, so accept every keyframe and use the actual min/max time
-                // the numbers are INT64_MIN/MAX, the 20000 is for safety because GenerateNodeAnimations uses an epsilon of 10000
-                start_time = -9223372036854775807ll + 20000;
-                stop_time = 9223372036854775807ll - 20000;
-            }
-
-            try {
-                for (const NodeMap::value_type& kv : node_map) {
-                    GenerateNodeAnimations(node_anims,
-                        kv.first,
-                        kv.second,
-                        layer_map,
-                        start_time, stop_time,
-                        max_time,
-                        min_time);
-                }
-            }
-            catch (std::exception&) {
-                std::for_each(node_anims.begin(), node_anims.end(), Util::delete_fun<aiNodeAnim>());
-                throw;
-            }
-
-            if (node_anims.size() || morphAnimDatas.size()) {
-                if (node_anims.size()) {
-                    anim->mChannels = new aiNodeAnim*[node_anims.size()]();
-                    anim->mNumChannels = static_cast<unsigned int>(node_anims.size());
-                    std::swap_ranges(node_anims.begin(), node_anims.end(), anim->mChannels);
-                }
-                if (morphAnimDatas.size()) {
-                    unsigned int numMorphMeshChannels = static_cast<unsigned int>(morphAnimDatas.size());
-                    anim->mMorphMeshChannels = new aiMeshMorphAnim*[numMorphMeshChannels];
-                    anim->mNumMorphMeshChannels = numMorphMeshChannels;
-                    unsigned int i = 0;
-                    for (auto morphAnimIt : morphAnimDatas) {
-                        morphAnimData* animData = morphAnimIt.second;
-                        unsigned int numKeys = static_cast<unsigned int>(animData->size());
-                        aiMeshMorphAnim* meshMorphAnim = new aiMeshMorphAnim();
-                        meshMorphAnim->mName.Set(morphAnimIt.first);
-                        meshMorphAnim->mNumKeys = numKeys;
-                        meshMorphAnim->mKeys = new aiMeshMorphKey[numKeys];
-                        unsigned int j = 0;
-                        for (auto animIt : *animData) {
-                            morphKeyData* keyData = animIt.second;
-                            unsigned int numValuesAndWeights = static_cast<unsigned int>(keyData->values.size());
-                            meshMorphAnim->mKeys[j].mNumValuesAndWeights = numValuesAndWeights;
-                            meshMorphAnim->mKeys[j].mValues = new unsigned int[numValuesAndWeights];
-                            meshMorphAnim->mKeys[j].mWeights = new double[numValuesAndWeights];
-                            meshMorphAnim->mKeys[j].mTime = CONVERT_FBX_TIME(animIt.first) * anim_fps;
-                            for (unsigned int k = 0; k < numValuesAndWeights; k++) {
-                                meshMorphAnim->mKeys[j].mValues[k] = keyData->values.at(k);
-                                meshMorphAnim->mKeys[j].mWeights[k] = keyData->weights.at(k);
-                            }
-                            j++;
-                        }
-                        anim->mMorphMeshChannels[i++] = meshMorphAnim;
-                    }
-                }
-            }
-            else {
-                // empty animations would fail validation, so drop them
-                delete anim;
-                animations.pop_back();
-                FBXImporter::LogInfo("ignoring empty AnimationStack (using IK?): " + name);
-                return;
-            }
-
-            double start_time_fps = has_local_startstop ? (CONVERT_FBX_TIME(start_time) * anim_fps) : min_time;
-            double stop_time_fps = has_local_startstop ? (CONVERT_FBX_TIME(stop_time) * anim_fps) : max_time;
-
-            // adjust relative timing for animation
-            for (unsigned int c = 0; c < anim->mNumChannels; c++) {
-                aiNodeAnim* channel = anim->mChannels[c];
-                for (uint32_t i = 0; i < channel->mNumPositionKeys; i++) {
-                    channel->mPositionKeys[i].mTime -= start_time_fps;
-                }
-                for (uint32_t i = 0; i < channel->mNumRotationKeys; i++) {
-                    channel->mRotationKeys[i].mTime -= start_time_fps;
-                }
-                for (uint32_t i = 0; i < channel->mNumScalingKeys; i++) {
-                    channel->mScalingKeys[i].mTime -= start_time_fps;
-                }
-            }
-            for (unsigned int c = 0; c < anim->mNumMorphMeshChannels; c++) {
-                aiMeshMorphAnim* channel = anim->mMorphMeshChannels[c];
-                for (uint32_t i = 0; i < channel->mNumKeys; i++) {
-                    channel->mKeys[i].mTime -= start_time_fps;
-                }
-            }
-
-            // for some mysterious reason, mDuration is simply the maximum key -- the
-            // validator always assumes animations to start at zero.
-            anim->mDuration = stop_time_fps - start_time_fps;
-            anim->mTicksPerSecond = anim_fps;
-        }
-
-        // ------------------------------------------------------------------------------------------------
-        void FBXConverter::ProcessMorphAnimDatas(std::map<std::string, morphAnimData*>* morphAnimDatas, const BlendShapeChannel* bsc, const AnimationCurveNode* node) {
-            std::vector<const Connection*> bscConnections = doc.GetConnectionsBySourceSequenced(bsc->ID(), "Deformer");
-            for (const Connection* bscConnection : bscConnections) {
-                auto bs = dynamic_cast<const BlendShape*>(bscConnection->DestinationObject());
-                if (bs) {
-                    auto channelIt = std::find(bs->BlendShapeChannels().begin(), bs->BlendShapeChannels().end(), bsc);
-                    if (channelIt != bs->BlendShapeChannels().end()) {
-                        auto channelIndex = static_cast<unsigned int>(std::distance(bs->BlendShapeChannels().begin(), channelIt));
-                        std::vector<const Connection*> bsConnections = doc.GetConnectionsBySourceSequenced(bs->ID(), "Geometry");
-                        for (const Connection* bsConnection : bsConnections) {
-                            auto geo = dynamic_cast<const Geometry*>(bsConnection->DestinationObject());
-                            if (geo) {
-                                std::vector<const Connection*> geoConnections = doc.GetConnectionsBySourceSequenced(geo->ID(), "Model");
-                                for (const Connection* geoConnection : geoConnections) {
-                                    auto model = dynamic_cast<const Model*>(geoConnection->DestinationObject());
-                                    if (model) {
-                                        auto geoIt = std::find(model->GetGeometry().begin(), model->GetGeometry().end(), geo);
-                                        auto geoIndex = static_cast<unsigned int>(std::distance(model->GetGeometry().begin(), geoIt));
-                                        auto name = aiString(FixNodeName(model->Name() + "*"));
-                                        name.length = 1 + ASSIMP_itoa10(name.data + name.length, MAXLEN - 1, geoIndex);
-                                        morphAnimData* animData;
-                                        auto animIt = morphAnimDatas->find(name.C_Str());
-                                        if (animIt == morphAnimDatas->end()) {
-                                            animData = new morphAnimData();
-                                            morphAnimDatas->insert(std::make_pair(name.C_Str(), animData));
-                                        }
-                                        else {
-                                            animData = animIt->second;
-                                        }
-                                        for (std::pair<std::string, const AnimationCurve*> curvesIt : node->Curves()) {
-                                            if (curvesIt.first == "d|DeformPercent") {
-                                                const AnimationCurve* animationCurve = curvesIt.second;
-                                                const KeyTimeList& keys = animationCurve->GetKeys();
-                                                const KeyValueList& values = animationCurve->GetValues();
-                                                unsigned int k = 0;
-                                                for (auto key : keys) {
-                                                    morphKeyData* keyData;
-                                                    auto keyIt = animData->find(key);
-                                                    if (keyIt == animData->end()) {
-                                                        keyData = new morphKeyData();
-                                                        animData->insert(std::make_pair(key, keyData));
-                                                    }
-                                                    else {
-                                                        keyData = keyIt->second;
-                                                    }
-                                                    keyData->values.push_back(channelIndex);
-                                                    keyData->weights.push_back(values.at(k) / 100.0f);
-                                                    k++;
-                                                }
-                                            }
-                                        }
-                                    }
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
-
-        // ------------------------------------------------------------------------------------------------
-#ifdef ASSIMP_BUILD_DEBUG
-        // ------------------------------------------------------------------------------------------------
-        // sanity check whether the input is ok
-        static void validateAnimCurveNodes(const std::vector<const AnimationCurveNode*>& curves,
-            bool strictMode) {
-            const Object* target(nullptr);
-            for (const AnimationCurveNode* node : curves) {
-                if (!target) {
-                    target = node->Target();
-                }
-                if (node->Target() != target) {
-                    FBXImporter::LogWarn("Node target is nullptr type.");
-                }
-                if (strictMode) {
-                    ai_assert(node->Target() == target);
-                }
-            }
-        }
-#endif // ASSIMP_BUILD_DEBUG
-
-        // ------------------------------------------------------------------------------------------------
-        void FBXConverter::GenerateNodeAnimations(std::vector<aiNodeAnim*>& node_anims,
-            const std::string& fixed_name,
-            const std::vector<const AnimationCurveNode*>& curves,
-            const LayerMap& layer_map,
-            int64_t start, int64_t stop,
-            double& max_time,
-            double& min_time)
-        {
-
-            NodeMap node_property_map;
-            ai_assert(curves.size());
-
-#ifdef ASSIMP_BUILD_DEBUG
-            validateAnimCurveNodes(curves, doc.Settings().strictMode);
-#endif
-            const AnimationCurveNode* curve_node = nullptr;
-            for (const AnimationCurveNode* node : curves) {
-                ai_assert(node);
-
-                if (node->TargetProperty().empty()) {
-                    FBXImporter::LogWarn("target property for animation curve not set: " + node->Name());
-                    continue;
-                }
-
-                curve_node = node;
-                if (node->Curves().empty()) {
-                    FBXImporter::LogWarn("no animation curves assigned to AnimationCurveNode: " + node->Name());
-                    continue;
-                }
-
-                node_property_map[node->TargetProperty()].push_back(node);
-            }
-
-            ai_assert(curve_node);
-            ai_assert(curve_node->TargetAsModel());
-
-            const Model& target = *curve_node->TargetAsModel();
-
-            // check for all possible transformation components
-            NodeMap::const_iterator chain[TransformationComp_MAXIMUM];
-
-            bool has_any = false;
-            bool has_complex = false;
-
-            for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i) {
-                const TransformationComp comp = static_cast<TransformationComp>(i);
-
-                // inverse pivots don't exist in the input, we just generate them
-                if (comp == TransformationComp_RotationPivotInverse || comp == TransformationComp_ScalingPivotInverse) {
-                    chain[i] = node_property_map.end();
-                    continue;
-                }
-
-                chain[i] = node_property_map.find(NameTransformationCompProperty(comp));
-                if (chain[i] != node_property_map.end()) {
-
-                    // check if this curves contains redundant information by looking
-                    // up the corresponding node's transformation chain.
-                    if (doc.Settings().optimizeEmptyAnimationCurves &&
-                        IsRedundantAnimationData(target, comp, (*chain[i]).second)) {
-
-                        FBXImporter::LogDebug("dropping redundant animation channel for node " + target.Name());
-                        continue;
-                    }
-
-                    has_any = true;
-
-                    if (comp != TransformationComp_Rotation && comp != TransformationComp_Scaling && comp != TransformationComp_Translation)
-                    {
-                        has_complex = true;
-                    }
-                }
-            }
-
-            if (!has_any) {
-                FBXImporter::LogWarn("ignoring node animation, did not find any transformation key frames");
-                return;
-            }
-
-            // this needs to play nicely with GenerateTransformationNodeChain() which will
-            // be invoked _later_ (animations come first). If this node has only rotation,
-            // scaling and translation _and_ there are no animated other components either,
-            // we can use a single node and also a single node animation channel.
-            if (!has_complex && !NeedsComplexTransformationChain(target)) {
-
-                aiNodeAnim* const nd = GenerateSimpleNodeAnim(fixed_name, target, chain,
-                    node_property_map.end(),
-                    layer_map,
-                    start, stop,
-                    max_time,
-                    min_time,
-                    true // input is TRS order, assimp is SRT
-                );
-
-                ai_assert(nd);
-                if (nd->mNumPositionKeys == 0 && nd->mNumRotationKeys == 0 && nd->mNumScalingKeys == 0) {
-                    delete nd;
-                }
-                else {
-                    node_anims.push_back(nd);
-                }
-                return;
-            }
-
-            // otherwise, things get gruesome and we need separate animation channels
-            // for each part of the transformation chain. Remember which channels
-            // we generated and pass this information to the node conversion
-            // code to avoid nodes that have identity transform, but non-identity
-            // animations, being dropped.
-            unsigned int flags = 0, bit = 0x1;
-            for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i, bit <<= 1) {
-                const TransformationComp comp = static_cast<TransformationComp>(i);
-
-                if (chain[i] != node_property_map.end()) {
-                    flags |= bit;
-
-                    ai_assert(comp != TransformationComp_RotationPivotInverse);
-                    ai_assert(comp != TransformationComp_ScalingPivotInverse);
-
-                    const std::string& chain_name = NameTransformationChainNode(fixed_name, comp);
-
-                    aiNodeAnim* na = nullptr;
-                    switch (comp)
-                    {
-                    case TransformationComp_Rotation:
-                    case TransformationComp_PreRotation:
-                    case TransformationComp_PostRotation:
-                    case TransformationComp_GeometricRotation:
-                        na = GenerateRotationNodeAnim(chain_name,
-                            target,
-                            (*chain[i]).second,
-                            layer_map,
-                            start, stop,
-                            max_time,
-                            min_time);
-
-                        break;
-
-                    case TransformationComp_RotationOffset:
-                    case TransformationComp_RotationPivot:
-                    case TransformationComp_ScalingOffset:
-                    case TransformationComp_ScalingPivot:
-                    case TransformationComp_Translation:
-                    case TransformationComp_GeometricTranslation:
-                        na = GenerateTranslationNodeAnim(chain_name,
-                            target,
-                            (*chain[i]).second,
-                            layer_map,
-                            start, stop,
-                            max_time,
-                            min_time);
-
-                        // pivoting requires us to generate an implicit inverse channel to undo the pivot translation
-                        if (comp == TransformationComp_RotationPivot) {
-                            const std::string& invName = NameTransformationChainNode(fixed_name,
-                                TransformationComp_RotationPivotInverse);
-
-                            aiNodeAnim* const inv = GenerateTranslationNodeAnim(invName,
-                                target,
-                                (*chain[i]).second,
-                                layer_map,
-                                start, stop,
-                                max_time,
-                                min_time,
-                                true);
-
-                            ai_assert(inv);
-                            if (inv->mNumPositionKeys == 0 && inv->mNumRotationKeys == 0 && inv->mNumScalingKeys == 0) {
-                                delete inv;
-                            }
-                            else {
-                                node_anims.push_back(inv);
-                            }
-
-                            ai_assert(TransformationComp_RotationPivotInverse > i);
-                            flags |= bit << (TransformationComp_RotationPivotInverse - i);
-                        }
-                        else if (comp == TransformationComp_ScalingPivot) {
-                            const std::string& invName = NameTransformationChainNode(fixed_name,
-                                TransformationComp_ScalingPivotInverse);
-
-                            aiNodeAnim* const inv = GenerateTranslationNodeAnim(invName,
-                                target,
-                                (*chain[i]).second,
-                                layer_map,
-                                start, stop,
-                                max_time,
-                                min_time,
-                                true);
-
-                            ai_assert(inv);
-                            if (inv->mNumPositionKeys == 0 && inv->mNumRotationKeys == 0 && inv->mNumScalingKeys == 0) {
-                                delete inv;
-                            }
-                            else {
-                                node_anims.push_back(inv);
-                            }
-
-                            ai_assert(TransformationComp_RotationPivotInverse > i);
-                            flags |= bit << (TransformationComp_RotationPivotInverse - i);
-                        }
-
-                        break;
-
-                    case TransformationComp_Scaling:
-                    case TransformationComp_GeometricScaling:
-                        na = GenerateScalingNodeAnim(chain_name,
-                            target,
-                            (*chain[i]).second,
-                            layer_map,
-                            start, stop,
-                            max_time,
-                            min_time);
-
-                        break;
-
-                    default:
-                        ai_assert(false);
-                    }
-
-                    ai_assert(na);
-                    if (na->mNumPositionKeys == 0 && na->mNumRotationKeys == 0 && na->mNumScalingKeys == 0) {
-                        delete na;
-                    }
-                    else {
-                        node_anims.push_back(na);
-                    }
-                    continue;
-                }
-            }
-
-            node_anim_chain_bits[fixed_name] = flags;
-        }
-
-
-        bool FBXConverter::IsRedundantAnimationData(const Model& target,
-            TransformationComp comp,
-            const std::vector<const AnimationCurveNode*>& curves) {
-            ai_assert(curves.size());
-
-            // look for animation nodes with
-            //  * sub channels for all relevant components set
-            //  * one key/value pair per component
-            //  * combined values match up the corresponding value in the bind pose node transformation
-            // only such nodes are 'redundant' for this function.
-
-            if (curves.size() > 1) {
-                return false;
-            }
-
-            const AnimationCurveNode& nd = *curves.front();
-            const AnimationCurveMap& sub_curves = nd.Curves();
-
-            const AnimationCurveMap::const_iterator dx = sub_curves.find("d|X");
-            const AnimationCurveMap::const_iterator dy = sub_curves.find("d|Y");
-            const AnimationCurveMap::const_iterator dz = sub_curves.find("d|Z");
-
-            if (dx == sub_curves.end() || dy == sub_curves.end() || dz == sub_curves.end()) {
-                return false;
-            }
-
-            const KeyValueList& vx = (*dx).second->GetValues();
-            const KeyValueList& vy = (*dy).second->GetValues();
-            const KeyValueList& vz = (*dz).second->GetValues();
-
-            if (vx.size() != 1 || vy.size() != 1 || vz.size() != 1) {
-                return false;
-            }
-
-            const aiVector3D dyn_val = aiVector3D(vx[0], vy[0], vz[0]);
-            const aiVector3D& static_val = PropertyGet<aiVector3D>(target.Props(),
-                NameTransformationCompProperty(comp),
-                TransformationCompDefaultValue(comp)
-                );
-
-            const float epsilon = Math::getEpsilon<float>();
-            return (dyn_val - static_val).SquareLength() < epsilon;
-        }
-
-
-        aiNodeAnim* FBXConverter::GenerateRotationNodeAnim(const std::string& name,
-            const Model& target,
-            const std::vector<const AnimationCurveNode*>& curves,
-            const LayerMap& layer_map,
-            int64_t start, int64_t stop,
-            double& max_time,
-            double& min_time)
-        {
-            std::unique_ptr<aiNodeAnim> na(new aiNodeAnim());
-            na->mNodeName.Set(name);
-
-            ConvertRotationKeys(na.get(), curves, layer_map, start, stop, max_time, min_time, target.RotationOrder());
-
-            // dummy scaling key
-            na->mScalingKeys = new aiVectorKey[1];
-            na->mNumScalingKeys = 1;
-
-            na->mScalingKeys[0].mTime = 0.;
-            na->mScalingKeys[0].mValue = aiVector3D(1.0f, 1.0f, 1.0f);
-
-            // dummy position key
-            na->mPositionKeys = new aiVectorKey[1];
-            na->mNumPositionKeys = 1;
-
-            na->mPositionKeys[0].mTime = 0.;
-            na->mPositionKeys[0].mValue = aiVector3D();
-
-            return na.release();
-        }
-
-        aiNodeAnim* FBXConverter::GenerateScalingNodeAnim(const std::string& name,
-            const Model& /*target*/,
-            const std::vector<const AnimationCurveNode*>& curves,
-            const LayerMap& layer_map,
-            int64_t start, int64_t stop,
-            double& max_time,
-            double& min_time)
-        {
-            std::unique_ptr<aiNodeAnim> na(new aiNodeAnim());
-            na->mNodeName.Set(name);
-
-            ConvertScaleKeys(na.get(), curves, layer_map, start, stop, max_time, min_time);
-
-            // dummy rotation key
-            na->mRotationKeys = new aiQuatKey[1];
-            na->mNumRotationKeys = 1;
-
-            na->mRotationKeys[0].mTime = 0.;
-            na->mRotationKeys[0].mValue = aiQuaternion();
-
-            // dummy position key
-            na->mPositionKeys = new aiVectorKey[1];
-            na->mNumPositionKeys = 1;
-
-            na->mPositionKeys[0].mTime = 0.;
-            na->mPositionKeys[0].mValue = aiVector3D();
-
-            return na.release();
-        }
-
-        aiNodeAnim* FBXConverter::GenerateTranslationNodeAnim(const std::string& name,
-            const Model& /*target*/,
-            const std::vector<const AnimationCurveNode*>& curves,
-            const LayerMap& layer_map,
-            int64_t start, int64_t stop,
-            double& max_time,
-            double& min_time,
-            bool inverse) {
-            std::unique_ptr<aiNodeAnim> na(new aiNodeAnim());
-            na->mNodeName.Set(name);
-
-            ConvertTranslationKeys(na.get(), curves, layer_map, start, stop, max_time, min_time);
-
-            if (inverse) {
-                for (unsigned int i = 0; i < na->mNumPositionKeys; ++i) {
-                    na->mPositionKeys[i].mValue *= -1.0f;
-                }
-            }
-
-            // dummy scaling key
-            na->mScalingKeys = new aiVectorKey[1];
-            na->mNumScalingKeys = 1;
-
-            na->mScalingKeys[0].mTime = 0.;
-            na->mScalingKeys[0].mValue = aiVector3D(1.0f, 1.0f, 1.0f);
-
-            // dummy rotation key
-            na->mRotationKeys = new aiQuatKey[1];
-            na->mNumRotationKeys = 1;
-
-            na->mRotationKeys[0].mTime = 0.;
-            na->mRotationKeys[0].mValue = aiQuaternion();
-
-            return na.release();
-        }
-
-        aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name,
-            const Model& target,
-            NodeMap::const_iterator chain[TransformationComp_MAXIMUM],
-            NodeMap::const_iterator iter_end,
-            const LayerMap& layer_map,
-            int64_t start, int64_t stop,
-            double& max_time,
-            double& min_time,
-            bool reverse_order)
-
-        {
-            std::unique_ptr<aiNodeAnim> na(new aiNodeAnim());
-            na->mNodeName.Set(name);
-
-            const PropertyTable& props = target.Props();
-
-            // need to convert from TRS order to SRT?
-            if (reverse_order) {
-
-                aiVector3D def_scale = PropertyGet(props, "Lcl Scaling", aiVector3D(1.f, 1.f, 1.f));
-                aiVector3D def_translate = PropertyGet(props, "Lcl Translation", aiVector3D(0.f, 0.f, 0.f));
-                aiVector3D def_rot = PropertyGet(props, "Lcl Rotation", aiVector3D(0.f, 0.f, 0.f));
-
-                KeyFrameListList scaling;
-                KeyFrameListList translation;
-                KeyFrameListList rotation;
-
-                if (chain[TransformationComp_Scaling] != iter_end) {
-                    scaling = GetKeyframeList((*chain[TransformationComp_Scaling]).second, start, stop);
-                }
-
-                if (chain[TransformationComp_Translation] != iter_end) {
-                    translation = GetKeyframeList((*chain[TransformationComp_Translation]).second, start, stop);
-                }
-
-                if (chain[TransformationComp_Rotation] != iter_end) {
-                    rotation = GetKeyframeList((*chain[TransformationComp_Rotation]).second, start, stop);
-                }
-
-                KeyFrameListList joined;
-                joined.insert(joined.end(), scaling.begin(), scaling.end());
-                joined.insert(joined.end(), translation.begin(), translation.end());
-                joined.insert(joined.end(), rotation.begin(), rotation.end());
-
-                const KeyTimeList& times = GetKeyTimeList(joined);
-
-                aiQuatKey* out_quat = new aiQuatKey[times.size()];
-                aiVectorKey* out_scale = new aiVectorKey[times.size()];
-                aiVectorKey* out_translation = new aiVectorKey[times.size()];
-
-                if (times.size())
-                {
-                    ConvertTransformOrder_TRStoSRT(out_quat, out_scale, out_translation,
-                        scaling,
-                        translation,
-                        rotation,
-                        times,
-                        max_time,
-                        min_time,
-                        target.RotationOrder(),
-                        def_scale,
-                        def_translate,
-                        def_rot);
-                }
-
-                // XXX remove duplicates / redundant keys which this operation did
-                // likely produce if not all three channels were equally dense.
-
-                na->mNumScalingKeys = static_cast<unsigned int>(times.size());
-                na->mNumRotationKeys = na->mNumScalingKeys;
-                na->mNumPositionKeys = na->mNumScalingKeys;
-
-                na->mScalingKeys = out_scale;
-                na->mRotationKeys = out_quat;
-                na->mPositionKeys = out_translation;
-            }
-            else {
-
-                // if a particular transformation is not given, grab it from
-                // the corresponding node to meet the semantics of aiNodeAnim,
-                // which requires all of rotation, scaling and translation
-                // to be set.
-                if (chain[TransformationComp_Scaling] != iter_end) {
-                    ConvertScaleKeys(na.get(), (*chain[TransformationComp_Scaling]).second,
-                        layer_map,
-                        start, stop,
-                        max_time,
-                        min_time);
-                }
-                else {
-                    na->mScalingKeys = new aiVectorKey[1];
-                    na->mNumScalingKeys = 1;
-
-                    na->mScalingKeys[0].mTime = 0.;
-                    na->mScalingKeys[0].mValue = PropertyGet(props, "Lcl Scaling",
-                        aiVector3D(1.f, 1.f, 1.f));
-                }
-
-                if (chain[TransformationComp_Rotation] != iter_end) {
-                    ConvertRotationKeys(na.get(), (*chain[TransformationComp_Rotation]).second,
-                        layer_map,
-                        start, stop,
-                        max_time,
-                        min_time,
-                        target.RotationOrder());
-                }
-                else {
-                    na->mRotationKeys = new aiQuatKey[1];
-                    na->mNumRotationKeys = 1;
-
-                    na->mRotationKeys[0].mTime = 0.;
-                    na->mRotationKeys[0].mValue = EulerToQuaternion(
-                        PropertyGet(props, "Lcl Rotation", aiVector3D(0.f, 0.f, 0.f)),
-                        target.RotationOrder());
-                }
-
-                if (chain[TransformationComp_Translation] != iter_end) {
-                    ConvertTranslationKeys(na.get(), (*chain[TransformationComp_Translation]).second,
-                        layer_map,
-                        start, stop,
-                        max_time,
-                        min_time);
-                }
-                else {
-                    na->mPositionKeys = new aiVectorKey[1];
-                    na->mNumPositionKeys = 1;
-
-                    na->mPositionKeys[0].mTime = 0.;
-                    na->mPositionKeys[0].mValue = PropertyGet(props, "Lcl Translation",
-                        aiVector3D(0.f, 0.f, 0.f));
-                }
-
-            }
-            return na.release();
-        }
-
-        FBXConverter::KeyFrameListList FBXConverter::GetKeyframeList(const std::vector<const AnimationCurveNode*>& nodes, int64_t start, int64_t stop)
-        {
-            KeyFrameListList inputs;
-            inputs.reserve(nodes.size() * 3);
-
-            //give some breathing room for rounding errors
-            int64_t adj_start = start - 10000;
-            int64_t adj_stop = stop + 10000;
-
-            for (const AnimationCurveNode* node : nodes) {
-                ai_assert(node);
-
-                const AnimationCurveMap& curves = node->Curves();
-                for (const AnimationCurveMap::value_type& kv : curves) {
-
-                    unsigned int mapto;
-                    if (kv.first == "d|X") {
-                        mapto = 0;
-                    }
-                    else if (kv.first == "d|Y") {
-                        mapto = 1;
-                    }
-                    else if (kv.first == "d|Z") {
-                        mapto = 2;
-                    }
-                    else {
-                        FBXImporter::LogWarn("ignoring scale animation curve, did not recognize target component");
-                        continue;
-                    }
-
-                    const AnimationCurve* const curve = kv.second;
-                    ai_assert(curve->GetKeys().size() == curve->GetValues().size() && curve->GetKeys().size());
-
-                    //get values within the start/stop time window
-                    std::shared_ptr<KeyTimeList> Keys(new KeyTimeList());
-                    std::shared_ptr<KeyValueList> Values(new KeyValueList());
-                    const size_t count = curve->GetKeys().size();
-                    Keys->reserve(count);
-                    Values->reserve(count);
-                    for (size_t n = 0; n < count; n++)
-                    {
-                        int64_t k = curve->GetKeys().at(n);
-                        if (k >= adj_start && k <= adj_stop)
-                        {
-                            Keys->push_back(k);
-                            Values->push_back(curve->GetValues().at(n));
-                        }
-                    }
-
-                    inputs.push_back(std::make_tuple(Keys, Values, mapto));
-                }
-            }
-            return inputs; // pray for NRVO :-)
-        }
-
-
-        KeyTimeList FBXConverter::GetKeyTimeList(const KeyFrameListList& inputs) {
-            ai_assert(!inputs.empty());
-
-            // reserve some space upfront - it is likely that the key-frame lists
-            // have matching time values, so max(of all key-frame lists) should
-            // be a good estimate.
-            KeyTimeList keys;
-
-            size_t estimate = 0;
-            for (const KeyFrameList& kfl : inputs) {
-                estimate = std::max(estimate, std::get<0>(kfl)->size());
-            }
-
-            keys.reserve(estimate);
-
-            std::vector<unsigned int> next_pos;
-            next_pos.resize(inputs.size(), 0);
-
-            const size_t count = inputs.size();
-            while (true) {
-
-                int64_t min_tick = std::numeric_limits<int64_t>::max();
-                for (size_t i = 0; i < count; ++i) {
-                    const KeyFrameList& kfl = inputs[i];
-
-                    if (std::get<0>(kfl)->size() > next_pos[i] && std::get<0>(kfl)->at(next_pos[i]) < min_tick) {
-                        min_tick = std::get<0>(kfl)->at(next_pos[i]);
-                    }
-                }
-
-                if (min_tick == std::numeric_limits<int64_t>::max()) {
-                    break;
-                }
-                keys.push_back(min_tick);
-
-                for (size_t i = 0; i < count; ++i) {
-                    const KeyFrameList& kfl = inputs[i];
-
-
-                    while (std::get<0>(kfl)->size() > next_pos[i] && std::get<0>(kfl)->at(next_pos[i]) == min_tick) {
-                        ++next_pos[i];
-                    }
-                }
-            }
-
-            return keys;
-        }
-
-        void FBXConverter::InterpolateKeys(aiVectorKey* valOut, const KeyTimeList& keys, const KeyFrameListList& inputs,
-            const aiVector3D& def_value,
-            double& max_time,
-            double& min_time) {
-            ai_assert(!keys.empty());
-            ai_assert(nullptr != valOut);
-
-            std::vector<unsigned int> next_pos;
-            const size_t count(inputs.size());
-
-            next_pos.resize(inputs.size(), 0);
-
-            for (KeyTimeList::value_type time : keys) {
-                ai_real result[3] = { def_value.x, def_value.y, def_value.z };
-
-                for (size_t i = 0; i < count; ++i) {
-                    const KeyFrameList& kfl = inputs[i];
-
-                    const size_t ksize = std::get<0>(kfl)->size();
-                    if (ksize == 0) {
-                        continue;
-                    }
-                    if (ksize > next_pos[i] && std::get<0>(kfl)->at(next_pos[i]) == time) {
-                        ++next_pos[i];
-                    }
-
-                    const size_t id0 = next_pos[i] > 0 ? next_pos[i] - 1 : 0;
-                    const size_t id1 = next_pos[i] == ksize ? ksize - 1 : next_pos[i];
-
-                    // use lerp for interpolation
-                    const KeyValueList::value_type valueA = std::get<1>(kfl)->at(id0);
-                    const KeyValueList::value_type valueB = std::get<1>(kfl)->at(id1);
-
-                    const KeyTimeList::value_type timeA = std::get<0>(kfl)->at(id0);
-                    const KeyTimeList::value_type timeB = std::get<0>(kfl)->at(id1);
-
-                    const ai_real factor = timeB == timeA ? ai_real(0.) : static_cast<ai_real>((time - timeA)) / (timeB - timeA);
-                    const ai_real interpValue = static_cast<ai_real>(valueA + (valueB - valueA) * factor);
-
-                    result[std::get<2>(kfl)] = interpValue;
-                }
-
-                // magic value to convert fbx times to seconds
-                valOut->mTime = CONVERT_FBX_TIME(time) * anim_fps;
-
-                min_time = std::min(min_time, valOut->mTime);
-                max_time = std::max(max_time, valOut->mTime);
-
-                valOut->mValue.x = result[0];
-                valOut->mValue.y = result[1];
-                valOut->mValue.z = result[2];
-
-                ++valOut;
-            }
-        }
-
-        void FBXConverter::InterpolateKeys(aiQuatKey* valOut, const KeyTimeList& keys, const KeyFrameListList& inputs,
-            const aiVector3D& def_value,
-            double& maxTime,
-            double& minTime,
-            Model::RotOrder order)
-        {
-            ai_assert(!keys.empty());
-            ai_assert(nullptr != valOut);
-
-            std::unique_ptr<aiVectorKey[]> temp(new aiVectorKey[keys.size()]);
-            InterpolateKeys(temp.get(), keys, inputs, def_value, maxTime, minTime);
-
-            aiMatrix4x4 m;
-
-            aiQuaternion lastq;
-
-            for (size_t i = 0, c = keys.size(); i < c; ++i) {
-
-                valOut[i].mTime = temp[i].mTime;
-
-                GetRotationMatrix(order, temp[i].mValue, m);
-                aiQuaternion quat = aiQuaternion(aiMatrix3x3(m));
-
-                // take shortest path by checking the inner product
-                // http://www.3dkingdoms.com/weekly/weekly.php?a=36
-                if (quat.x * lastq.x + quat.y * lastq.y + quat.z * lastq.z + quat.w * lastq.w < 0)
-                {
-                    quat.x = -quat.x;
-                    quat.y = -quat.y;
-                    quat.z = -quat.z;
-                    quat.w = -quat.w;
-                }
-                lastq = quat;
-
-                valOut[i].mValue = quat;
-            }
-        }
-
-        void FBXConverter::ConvertTransformOrder_TRStoSRT(aiQuatKey* out_quat, aiVectorKey* out_scale,
-            aiVectorKey* out_translation,
-            const KeyFrameListList& scaling,
-            const KeyFrameListList& translation,
-            const KeyFrameListList& rotation,
-            const KeyTimeList& times,
-            double& maxTime,
-            double& minTime,
-            Model::RotOrder order,
-            const aiVector3D& def_scale,
-            const aiVector3D& def_translate,
-            const aiVector3D& def_rotation)
-        {
-            if (rotation.size()) {
-                InterpolateKeys(out_quat, times, rotation, def_rotation, maxTime, minTime, order);
-            }
-            else {
-                for (size_t i = 0; i < times.size(); ++i) {
-                    out_quat[i].mTime = CONVERT_FBX_TIME(times[i]) * anim_fps;
-                    out_quat[i].mValue = EulerToQuaternion(def_rotation, order);
-                }
-            }
-
-            if (scaling.size()) {
-                InterpolateKeys(out_scale, times, scaling, def_scale, maxTime, minTime);
-            }
-            else {
-                for (size_t i = 0; i < times.size(); ++i) {
-                    out_scale[i].mTime = CONVERT_FBX_TIME(times[i]) * anim_fps;
-                    out_scale[i].mValue = def_scale;
-                }
-            }
-
-            if (translation.size()) {
-                InterpolateKeys(out_translation, times, translation, def_translate, maxTime, minTime);
-            }
-            else {
-                for (size_t i = 0; i < times.size(); ++i) {
-                    out_translation[i].mTime = CONVERT_FBX_TIME(times[i]) * anim_fps;
-                    out_translation[i].mValue = def_translate;
-                }
-            }
-
-            const size_t count = times.size();
-            for (size_t i = 0; i < count; ++i) {
-                aiQuaternion& r = out_quat[i].mValue;
-                aiVector3D& s = out_scale[i].mValue;
-                aiVector3D& t = out_translation[i].mValue;
-
-                aiMatrix4x4 mat, temp;
-                aiMatrix4x4::Translation(t, mat);
-                mat *= aiMatrix4x4(r.GetMatrix());
-                mat *= aiMatrix4x4::Scaling(s, temp);
-
-                mat.Decompose(s, r, t);
-            }
-        }
-
-        aiQuaternion FBXConverter::EulerToQuaternion(const aiVector3D& rot, Model::RotOrder order)
-        {
-            aiMatrix4x4 m;
-            GetRotationMatrix(order, rot, m);
-
-            return aiQuaternion(aiMatrix3x3(m));
-        }
-
-        void FBXConverter::ConvertScaleKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, const LayerMap& /*layers*/,
-            int64_t start, int64_t stop,
-            double& maxTime,
-            double& minTime)
-        {
-            ai_assert(nodes.size());
-
-            // XXX for now, assume scale should be blended geometrically (i.e. two
-            // layers should be multiplied with each other). There is a FBX
-            // property in the layer to specify the behaviour, though.
-
-            const KeyFrameListList& inputs = GetKeyframeList(nodes, start, stop);
-            const KeyTimeList& keys = GetKeyTimeList(inputs);
-
-            na->mNumScalingKeys = static_cast<unsigned int>(keys.size());
-            na->mScalingKeys = new aiVectorKey[keys.size()];
-            if (keys.size() > 0) {
-                InterpolateKeys(na->mScalingKeys, keys, inputs, aiVector3D(1.0f, 1.0f, 1.0f), maxTime, minTime);
-            }
-        }
-
-        void FBXConverter::ConvertTranslationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
-            const LayerMap& /*layers*/,
-            int64_t start, int64_t stop,
-            double& maxTime,
-            double& minTime)
-        {
-            ai_assert(nodes.size());
-
-            // XXX see notes in ConvertScaleKeys()
-            const KeyFrameListList& inputs = GetKeyframeList(nodes, start, stop);
-            const KeyTimeList& keys = GetKeyTimeList(inputs);
-
-            na->mNumPositionKeys = static_cast<unsigned int>(keys.size());
-            na->mPositionKeys = new aiVectorKey[keys.size()];
-            if (keys.size() > 0)
-                InterpolateKeys(na->mPositionKeys, keys, inputs, aiVector3D(0.0f, 0.0f, 0.0f), maxTime, minTime);
-        }
-
-        void FBXConverter::ConvertRotationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
-            const LayerMap& /*layers*/,
-            int64_t start, int64_t stop,
-            double& maxTime,
-            double& minTime,
-            Model::RotOrder order)
-        {
-            ai_assert(nodes.size());
-
-            // XXX see notes in ConvertScaleKeys()
-            const std::vector< KeyFrameList >& inputs = GetKeyframeList(nodes, start, stop);
-            const KeyTimeList& keys = GetKeyTimeList(inputs);
-
-            na->mNumRotationKeys = static_cast<unsigned int>(keys.size());
-            na->mRotationKeys = new aiQuatKey[keys.size()];
-            if (!keys.empty()) {
-                InterpolateKeys(na->mRotationKeys, keys, inputs, aiVector3D(0.0f, 0.0f, 0.0f), maxTime, minTime, order);
-            }
-        }
-
-        void FBXConverter::ConvertGlobalSettings() {
-            if (nullptr == out) {
-                return;
-            }
-
-            out->mMetaData = aiMetadata::Alloc(15);
-            out->mMetaData->Set(0, "UpAxis", doc.GlobalSettings().UpAxis());
-            out->mMetaData->Set(1, "UpAxisSign", doc.GlobalSettings().UpAxisSign());
-            out->mMetaData->Set(2, "FrontAxis", doc.GlobalSettings().FrontAxis());
-            out->mMetaData->Set(3, "FrontAxisSign", doc.GlobalSettings().FrontAxisSign());
-            out->mMetaData->Set(4, "CoordAxis", doc.GlobalSettings().CoordAxis());
-            out->mMetaData->Set(5, "CoordAxisSign", doc.GlobalSettings().CoordAxisSign());
-            out->mMetaData->Set(6, "OriginalUpAxis", doc.GlobalSettings().OriginalUpAxis());
-            out->mMetaData->Set(7, "OriginalUpAxisSign", doc.GlobalSettings().OriginalUpAxisSign());
-            out->mMetaData->Set(8, "UnitScaleFactor", (double)doc.GlobalSettings().UnitScaleFactor());
-            out->mMetaData->Set(9, "OriginalUnitScaleFactor", doc.GlobalSettings().OriginalUnitScaleFactor());
-            out->mMetaData->Set(10, "AmbientColor", doc.GlobalSettings().AmbientColor());
-            out->mMetaData->Set(11, "FrameRate", (int)doc.GlobalSettings().TimeMode());
-            out->mMetaData->Set(12, "TimeSpanStart", doc.GlobalSettings().TimeSpanStart());
-            out->mMetaData->Set(13, "TimeSpanStop", doc.GlobalSettings().TimeSpanStop());
-            out->mMetaData->Set(14, "CustomFrameRate", doc.GlobalSettings().CustomFrameRate());
-        }
-
-        void FBXConverter::TransferDataToScene()
-        {
-            ai_assert(!out->mMeshes);
-            ai_assert(!out->mNumMeshes);
-
-            // note: the trailing () ensures initialization with nullptr - not
-            // many C++ users seem to know this, so pointing it out to avoid
-            // confusion why this code works.
-
-            if (meshes.size()) {
-                out->mMeshes = new aiMesh*[meshes.size()]();
-                out->mNumMeshes = static_cast<unsigned int>(meshes.size());
-
-                std::swap_ranges(meshes.begin(), meshes.end(), out->mMeshes);
-            }
-
-            if (materials.size()) {
-                out->mMaterials = new aiMaterial*[materials.size()]();
-                out->mNumMaterials = static_cast<unsigned int>(materials.size());
-
-                std::swap_ranges(materials.begin(), materials.end(), out->mMaterials);
-            }
-
-            if (animations.size()) {
-                out->mAnimations = new aiAnimation*[animations.size()]();
-                out->mNumAnimations = static_cast<unsigned int>(animations.size());
-
-                std::swap_ranges(animations.begin(), animations.end(), out->mAnimations);
-            }
-
-            if (lights.size()) {
-                out->mLights = new aiLight*[lights.size()]();
-                out->mNumLights = static_cast<unsigned int>(lights.size());
-
-                std::swap_ranges(lights.begin(), lights.end(), out->mLights);
-            }
-
-            if (cameras.size()) {
-                out->mCameras = new aiCamera*[cameras.size()]();
-                out->mNumCameras = static_cast<unsigned int>(cameras.size());
-
-                std::swap_ranges(cameras.begin(), cameras.end(), out->mCameras);
-            }
-
-            if (textures.size()) {
-                out->mTextures = new aiTexture*[textures.size()]();
-                out->mNumTextures = static_cast<unsigned int>(textures.size());
-
-                std::swap_ranges(textures.begin(), textures.end(), out->mTextures);
-            }
-        }
-
-        void FBXConverter::ConvertOrphantEmbeddedTextures()
-        {
-            // in C++14 it could be:
-            // for (auto&& [id, object] : objects)
-            for (auto&& id_and_object : doc.Objects())
-            {
-                auto&& id = std::get<0>(id_and_object);
-                auto&& object = std::get<1>(id_and_object);
-                // If an object doesn't have parent
-                if (doc.ConnectionsBySource().count(id) == 0)
-                {
-                    const Texture* realTexture = nullptr;
-                    try
-                    {
-                        const auto& element = object->GetElement();
-                        const Token& key = element.KeyToken();
-                        const char* obtype = key.begin();
-                        const size_t length = static_cast<size_t>(key.end() - key.begin());
-                        if (strncmp(obtype, "Texture", length) == 0)
-                        {
-                            const Texture* texture = static_cast<const Texture*>(object->Get());
-                            if (texture->Media() && texture->Media()->ContentLength() > 0)
-                            {
-                                realTexture = texture;
-                            }
-                        }
-                    }
-                    catch (...)
-                    {
-                        // do nothing
-                    }
-                    if (realTexture)
-                    {
-                        const Video* media = realTexture->Media();
-                        unsigned int index = ConvertVideo(*media);
-                        textures_converted[*media] = index;
-                    }
-                }
-            }
-        }
-
-        // ------------------------------------------------------------------------------------------------
-        void ConvertToAssimpScene(aiScene* out, const Document& doc, bool removeEmptyBones)
-        {
-            FBXConverter converter(out, doc, removeEmptyBones);
-        }
-
-    } // !FBX
-} // !Assimp
-
-#endif

+ 0 - 491
thirdparty/assimp/code/FBX/FBXConverter.h

@@ -1,491 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file  FBXDConverter.h
- *  @brief FBX DOM to aiScene conversion
- */
-#ifndef INCLUDED_AI_FBX_CONVERTER_H
-#define INCLUDED_AI_FBX_CONVERTER_H
-
-#include "FBXParser.h"
-#include "FBXMeshGeometry.h"
-#include "FBXDocument.h"
-#include "FBXUtil.h"
-#include "FBXProperties.h"
-#include "FBXImporter.h"
-
-#include <assimp/anim.h>
-#include <assimp/material.h>
-#include <assimp/light.h>
-#include <assimp/texture.h>
-#include <assimp/camera.h>
-#include <assimp/StringComparison.h>
-#include <unordered_map>
-#include <unordered_set>
-
-struct aiScene;
-struct aiNode;
-struct aiMaterial;
-
-struct morphKeyData {
-    std::vector<unsigned int> values;
-    std::vector<float> weights;
-};
-typedef std::map<int64_t, morphKeyData*> morphAnimData;
-
-namespace Assimp {
-namespace FBX {
-
-class Document;
-/** 
- *  Convert a FBX #Document to #aiScene
- *  @param out Empty scene to be populated
- *  @param doc Parsed FBX document
- *  @param removeEmptyBones Will remove bones, which do not have any references to vertices.
- */
-void ConvertToAssimpScene(aiScene* out, const Document& doc, bool removeEmptyBones);
-
-/** Dummy class to encapsulate the conversion process */
-class FBXConverter {
-public:
-    /**
-    *  The different parts that make up the final local transformation of a fbx-node
-    */
-    enum TransformationComp {
-        TransformationComp_GeometricScalingInverse = 0,
-        TransformationComp_GeometricRotationInverse,
-        TransformationComp_GeometricTranslationInverse,
-        TransformationComp_Translation,
-        TransformationComp_RotationOffset,
-        TransformationComp_RotationPivot,
-        TransformationComp_PreRotation,
-        TransformationComp_Rotation,
-        TransformationComp_PostRotation,
-        TransformationComp_RotationPivotInverse,
-        TransformationComp_ScalingOffset,
-        TransformationComp_ScalingPivot,
-        TransformationComp_Scaling,
-        TransformationComp_ScalingPivotInverse,
-        TransformationComp_GeometricTranslation,
-        TransformationComp_GeometricRotation,
-        TransformationComp_GeometricScaling,
-
-        TransformationComp_MAXIMUM
-    };
-
-public:
-    FBXConverter(aiScene* out, const Document& doc, bool removeEmptyBones);
-    ~FBXConverter();
-
-private:
-    // ------------------------------------------------------------------------------------------------
-    // find scene root and trigger recursive scene conversion
-    void ConvertRootNode();
-
-    // ------------------------------------------------------------------------------------------------
-    // collect and assign child nodes
-    void ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node);
-
-    // ------------------------------------------------------------------------------------------------
-    void ConvertLights(const Model& model, const std::string &orig_name );
-
-    // ------------------------------------------------------------------------------------------------
-    void ConvertCameras(const Model& model, const std::string &orig_name );
-
-    // ------------------------------------------------------------------------------------------------
-    void ConvertLight( const Light& light, const std::string &orig_name );
-
-    // ------------------------------------------------------------------------------------------------
-    void ConvertCamera( const Camera& cam, const std::string &orig_name );
-
-    // ------------------------------------------------------------------------------------------------
-    void GetUniqueName( const std::string &name, std::string& uniqueName );
-
-    // ------------------------------------------------------------------------------------------------
-    // this returns unified names usable within assimp identifiers (i.e. no space characters -
-    // while these would be allowed, they are a potential trouble spot so better not use them).
-    const char* NameTransformationComp(TransformationComp comp);
-
-    // ------------------------------------------------------------------------------------------------
-    // Returns an unique name for a node or traverses up a hierarchy until a non-empty name is found and
-    // then makes this name unique
-    std::string MakeUniqueNodeName(const Model* const model, const aiNode& parent);
-
-    // ------------------------------------------------------------------------------------------------
-    // note: this returns the REAL fbx property names
-    const char* NameTransformationCompProperty(TransformationComp comp);
-
-    // ------------------------------------------------------------------------------------------------
-    aiVector3D TransformationCompDefaultValue(TransformationComp comp);
-
-    // ------------------------------------------------------------------------------------------------
-    void GetRotationMatrix(Model::RotOrder mode, const aiVector3D& rotation, aiMatrix4x4& out);
-    // ------------------------------------------------------------------------------------------------
-    /**
-    *  checks if a node has more than just scaling, rotation and translation components
-    */
-    bool NeedsComplexTransformationChain(const Model& model);
-
-    // ------------------------------------------------------------------------------------------------
-    // note: name must be a FixNodeName() result
-    std::string NameTransformationChainNode(const std::string& name, TransformationComp comp);
-
-    // ------------------------------------------------------------------------------------------------
-    /**
-    *  note: memory for output_nodes will be managed by the caller
-    */
-    bool GenerateTransformationNodeChain(const Model& model, const std::string& name, std::vector<aiNode*>& output_nodes, std::vector<aiNode*>& post_output_nodes);
-
-    // ------------------------------------------------------------------------------------------------
-    void SetupNodeMetadata(const Model& model, aiNode& nd);
-
-    // ------------------------------------------------------------------------------------------------
-    void ConvertModel(const Model &model, aiNode *parent, aiNode *root_node,
-                      const aiMatrix4x4 &absolute_transform);
-    
-    // ------------------------------------------------------------------------------------------------
-    // MeshGeometry -> aiMesh, return mesh index + 1 or 0 if the conversion failed
-    std::vector<unsigned int>
-    ConvertMesh(const MeshGeometry &mesh, const Model &model, aiNode *parent, aiNode *root_node,
-                const aiMatrix4x4 &absolute_transform);
-
-    // ------------------------------------------------------------------------------------------------
-    std::vector<unsigned int> ConvertLine(const LineGeometry& line, const Model& model,
-                                          aiNode *parent, aiNode *root_node);
-
-    // ------------------------------------------------------------------------------------------------
-    aiMesh* SetupEmptyMesh(const Geometry& mesh, aiNode *parent);
-
-    // ------------------------------------------------------------------------------------------------
-    unsigned int ConvertMeshSingleMaterial(const MeshGeometry &mesh, const Model &model,
-                                           const aiMatrix4x4 &absolute_transform, aiNode *parent,
-                                           aiNode *root_node);
-
-    // ------------------------------------------------------------------------------------------------
-    std::vector<unsigned int>
-    ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, aiNode *parent, aiNode *root_node,
-                             const aiMatrix4x4 &absolute_transform);
-
-    // ------------------------------------------------------------------------------------------------
-    unsigned int ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, MatIndexArray::value_type index,
-                                          aiNode *parent, aiNode *root_node, const aiMatrix4x4 &absolute_transform);
-
-    // ------------------------------------------------------------------------------------------------
-    static const unsigned int NO_MATERIAL_SEPARATION = /* std::numeric_limits<unsigned int>::max() */
-        static_cast<unsigned int>(-1);
-
-    // ------------------------------------------------------------------------------------------------
-    /**
-    *  - if materialIndex == NO_MATERIAL_SEPARATION, materials are not taken into
-    *    account when determining which weights to include.
-    *  - outputVertStartIndices is only used when a material index is specified, it gives for
-    *    each output vertex the DOM index it maps to.
-    */
-    void ConvertWeights(aiMesh *out, const Model &model, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform,
-                        aiNode *parent = NULL, aiNode *root_node = NULL,
-                        unsigned int materialIndex = NO_MATERIAL_SEPARATION,
-                        std::vector<unsigned int> *outputVertStartIndices = NULL);
-    // lookup
-    static const aiNode* GetNodeByName( const aiString& name, aiNode *current_node );
-    // ------------------------------------------------------------------------------------------------
-    void ConvertCluster(std::vector<aiBone *> &local_mesh_bones, const Cluster *cl,
-                        std::vector<size_t> &out_indices, std::vector<size_t> &index_out_indices,
-                        std::vector<size_t> &count_out_indices, const aiMatrix4x4 &absolute_transform,
-                        aiNode *parent, aiNode *root_node);
-
-    // ------------------------------------------------------------------------------------------------
-    void ConvertMaterialForMesh(aiMesh* out, const Model& model, const MeshGeometry& geo,
-        MatIndexArray::value_type materialIndex);
-
-    // ------------------------------------------------------------------------------------------------
-    unsigned int GetDefaultMaterial();
-
-    // ------------------------------------------------------------------------------------------------
-    // Material -> aiMaterial
-    unsigned int ConvertMaterial(const Material& material, const MeshGeometry* const mesh);
-
-    // ------------------------------------------------------------------------------------------------
-    // Video -> aiTexture
-    unsigned int ConvertVideo(const Video& video);
-
-    // ------------------------------------------------------------------------------------------------
-    // convert embedded texture if necessary and return actual texture path
-    aiString GetTexturePath(const Texture* tex);
-
-    // ------------------------------------------------------------------------------------------------
-    void TrySetTextureProperties(aiMaterial* out_mat, const TextureMap& textures,
-        const std::string& propName,
-        aiTextureType target, const MeshGeometry* const mesh);
-
-    // ------------------------------------------------------------------------------------------------
-    void TrySetTextureProperties(aiMaterial* out_mat, const LayeredTextureMap& layeredTextures,
-        const std::string& propName,
-        aiTextureType target, const MeshGeometry* const mesh);
-
-    // ------------------------------------------------------------------------------------------------
-    void SetTextureProperties(aiMaterial* out_mat, const TextureMap& textures, const MeshGeometry* const mesh);
-
-    // ------------------------------------------------------------------------------------------------
-    void SetTextureProperties(aiMaterial* out_mat, const LayeredTextureMap& layeredTextures, const MeshGeometry* const mesh);
-
-    // ------------------------------------------------------------------------------------------------
-    aiColor3D GetColorPropertyFromMaterial(const PropertyTable& props, const std::string& baseName,
-        bool& result);
-    aiColor3D GetColorPropertyFactored(const PropertyTable& props, const std::string& colorName,
-        const std::string& factorName, bool& result, bool useTemplate = true);
-    aiColor3D GetColorProperty(const PropertyTable& props, const std::string& colorName,
-        bool& result, bool useTemplate = true);
-
-    // ------------------------------------------------------------------------------------------------
-    void SetShadingPropertiesCommon(aiMaterial* out_mat, const PropertyTable& props);
-    void SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTable& props, const TextureMap& textures, const MeshGeometry* const mesh);
-
-    // ------------------------------------------------------------------------------------------------
-    // get the number of fps for a FrameRate enumerated value
-    static double FrameRateToDouble(FileGlobalSettings::FrameRate fp, double customFPSVal = -1.0);
-
-    // ------------------------------------------------------------------------------------------------
-    // convert animation data to aiAnimation et al
-    void ConvertAnimations();
-
-    // ------------------------------------------------------------------------------------------------
-    // takes a fbx node name and returns the identifier to be used in the assimp output scene.
-    // the function is guaranteed to provide consistent results over multiple invocations
-    // UNLESS RenameNode() is called for a particular node name.
-    std::string FixNodeName(const std::string& name);
-    std::string FixAnimMeshName(const std::string& name);
-
-    typedef std::map<const AnimationCurveNode*, const AnimationLayer*> LayerMap;
-
-    // XXX: better use multi_map ..
-    typedef std::map<std::string, std::vector<const AnimationCurveNode*> > NodeMap;
-
-    // ------------------------------------------------------------------------------------------------
-    void ConvertAnimationStack(const AnimationStack& st);
-
-    // ------------------------------------------------------------------------------------------------
-    void ProcessMorphAnimDatas(std::map<std::string, morphAnimData*>* morphAnimDatas, const BlendShapeChannel* bsc, const AnimationCurveNode* node);
-
-    // ------------------------------------------------------------------------------------------------
-    void GenerateNodeAnimations(std::vector<aiNodeAnim*>& node_anims,
-        const std::string& fixed_name,
-        const std::vector<const AnimationCurveNode*>& curves,
-        const LayerMap& layer_map,
-        int64_t start, int64_t stop,
-        double& max_time,
-        double& min_time);
-
-    // ------------------------------------------------------------------------------------------------
-    bool IsRedundantAnimationData(const Model& target,
-        TransformationComp comp,
-        const std::vector<const AnimationCurveNode*>& curves);
-
-    // ------------------------------------------------------------------------------------------------
-    aiNodeAnim* GenerateRotationNodeAnim(const std::string& name,
-        const Model& target,
-        const std::vector<const AnimationCurveNode*>& curves,
-        const LayerMap& layer_map,
-        int64_t start, int64_t stop,
-        double& max_time,
-        double& min_time);
-
-    // ------------------------------------------------------------------------------------------------
-    aiNodeAnim* GenerateScalingNodeAnim(const std::string& name,
-        const Model& /*target*/,
-        const std::vector<const AnimationCurveNode*>& curves,
-        const LayerMap& layer_map,
-        int64_t start, int64_t stop,
-        double& max_time,
-        double& min_time);
-
-    // ------------------------------------------------------------------------------------------------
-    aiNodeAnim* GenerateTranslationNodeAnim(const std::string& name,
-        const Model& /*target*/,
-        const std::vector<const AnimationCurveNode*>& curves,
-        const LayerMap& layer_map,
-        int64_t start, int64_t stop,
-        double& max_time,
-        double& min_time,
-        bool inverse = false);
-
-    // ------------------------------------------------------------------------------------------------
-    // generate node anim, extracting only Rotation, Scaling and Translation from the given chain
-    aiNodeAnim* GenerateSimpleNodeAnim(const std::string& name,
-        const Model& target,
-        NodeMap::const_iterator chain[TransformationComp_MAXIMUM],
-        NodeMap::const_iterator iter_end,
-        const LayerMap& layer_map,
-        int64_t start, int64_t stop,
-        double& max_time,
-        double& min_time,
-        bool reverse_order = false);
-
-    // key (time), value, mapto (component index)
-    typedef std::tuple<std::shared_ptr<KeyTimeList>, std::shared_ptr<KeyValueList>, unsigned int > KeyFrameList;
-    typedef std::vector<KeyFrameList> KeyFrameListList;
-
-    // ------------------------------------------------------------------------------------------------
-    KeyFrameListList GetKeyframeList(const std::vector<const AnimationCurveNode*>& nodes, int64_t start, int64_t stop);
-
-    // ------------------------------------------------------------------------------------------------
-    KeyTimeList GetKeyTimeList(const KeyFrameListList& inputs);
-
-    // ------------------------------------------------------------------------------------------------
-    void InterpolateKeys(aiVectorKey* valOut, const KeyTimeList& keys, const KeyFrameListList& inputs,
-        const aiVector3D& def_value,
-        double& max_time,
-        double& min_time);
-
-    // ------------------------------------------------------------------------------------------------
-    void InterpolateKeys(aiQuatKey* valOut, const KeyTimeList& keys, const KeyFrameListList& inputs,
-        const aiVector3D& def_value,
-        double& maxTime,
-        double& minTime,
-        Model::RotOrder order);
-
-    // ------------------------------------------------------------------------------------------------
-    void ConvertTransformOrder_TRStoSRT(aiQuatKey* out_quat, aiVectorKey* out_scale,
-        aiVectorKey* out_translation,
-        const KeyFrameListList& scaling,
-        const KeyFrameListList& translation,
-        const KeyFrameListList& rotation,
-        const KeyTimeList& times,
-        double& maxTime,
-        double& minTime,
-        Model::RotOrder order,
-        const aiVector3D& def_scale,
-        const aiVector3D& def_translate,
-        const aiVector3D& def_rotation);
-
-    // ------------------------------------------------------------------------------------------------
-    // euler xyz -> quat
-    aiQuaternion EulerToQuaternion(const aiVector3D& rot, Model::RotOrder order);
-
-    // ------------------------------------------------------------------------------------------------
-    void ConvertScaleKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, const LayerMap& /*layers*/,
-        int64_t start, int64_t stop,
-        double& maxTime,
-        double& minTime);
-
-    // ------------------------------------------------------------------------------------------------
-    void ConvertTranslationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
-        const LayerMap& /*layers*/,
-        int64_t start, int64_t stop,
-        double& maxTime,
-        double& minTime);
-
-    // ------------------------------------------------------------------------------------------------
-    void ConvertRotationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
-        const LayerMap& /*layers*/,
-        int64_t start, int64_t stop,
-        double& maxTime,
-        double& minTime,
-        Model::RotOrder order);
-
-    void ConvertGlobalSettings();
-
-    // ------------------------------------------------------------------------------------------------
-    // copy generated meshes, animations, lights, cameras and textures to the output scene
-    void TransferDataToScene();
-
-    // ------------------------------------------------------------------------------------------------
-    // FBX file could have embedded textures not connected to anything
-    void ConvertOrphantEmbeddedTextures();
-
-private:
-    // 0: not assigned yet, others: index is value - 1
-    unsigned int defaultMaterialIndex;
-
-    std::vector<aiMesh*> meshes;
-    std::vector<aiMaterial*> materials;
-    std::vector<aiAnimation*> animations;
-    std::vector<aiLight*> lights;
-    std::vector<aiCamera*> cameras;
-    std::vector<aiTexture*> textures;
-
-    using MaterialMap = std::fbx_unordered_map<const Material*, unsigned int>;
-    MaterialMap materials_converted;
-
-    using VideoMap = std::fbx_unordered_map<const Video, unsigned int>;
-    VideoMap textures_converted;
-
-    using MeshMap = std::fbx_unordered_map<const Geometry*, std::vector<unsigned int> >;
-    MeshMap meshes_converted;
-
-    // fixed node name -> which trafo chain components have animations?
-    using NodeAnimBitMap = std::fbx_unordered_map<std::string, unsigned int> ;
-    NodeAnimBitMap node_anim_chain_bits;
-
-    // number of nodes with the same name
-    using NodeNameCache = std::fbx_unordered_map<std::string, unsigned int>;
-    NodeNameCache mNodeNames;
-
-    // Deformer name is not the same as a bone name - it does contain the bone name though :)
-    // Deformer names in FBX are always unique in an FBX file.
-    std::map<const std::string, aiBone *> bone_map;
-
-    double anim_fps;
-
-    aiScene* const out;
-    const FBX::Document& doc;
-
-    static void BuildBoneList(aiNode *current_node, const aiNode *root_node, const aiScene *scene,
-                             std::vector<aiBone*>& bones);
-
-    void BuildBoneStack(aiNode *current_node, const aiNode *root_node, const aiScene *scene,
-                   const std::vector<aiBone *> &bones,
-                   std::map<aiBone *, aiNode *> &bone_stack,
-                   std::vector<aiNode*> &node_stack );
-
-    static void BuildNodeList(aiNode *current_node, std::vector<aiNode *> &nodes);
-
-    static aiNode *GetNodeFromStack(const aiString &node_name, std::vector<aiNode *> &nodes);
-
-    static aiNode *GetArmatureRoot(aiNode *bone_node, std::vector<aiBone*> &bone_list);
-
-    static bool IsBoneNode(const aiString &bone_name, std::vector<aiBone *> &bones);
-};
-
-}
-}
-
-#endif // INCLUDED_AI_FBX_CONVERTER_H

+ 0 - 213
thirdparty/assimp/code/FBX/FBXDeformer.cpp

@@ -1,213 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file  FBXNoteAttribute.cpp
- *  @brief Assimp::FBX::NodeAttribute (and subclasses) implementation
- */
-
-#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
-
-#include "FBXParser.h"
-#include "FBXDocument.h"
-#include "FBXMeshGeometry.h"
-#include "FBXImporter.h"
-#include "FBXDocumentUtil.h"
-
-namespace Assimp {
-namespace FBX {
-
-using namespace Util;
-
-// ------------------------------------------------------------------------------------------------
-Deformer::Deformer(uint64_t id, const Element& element, const Document& doc, const std::string& name)
-    : Object(id,element,name)
-{
-    const Scope& sc = GetRequiredScope(element);
-
-    const std::string& classname = ParseTokenAsString(GetRequiredToken(element,2));
-    props = GetPropertyTable(doc,"Deformer.Fbx" + classname,element,sc,true);
-}
-
-
-// ------------------------------------------------------------------------------------------------
-Deformer::~Deformer()
-{
-
-}
-
-
-// ------------------------------------------------------------------------------------------------
-Cluster::Cluster(uint64_t id, const Element& element, const Document& doc, const std::string& name)
-: Deformer(id,element,doc,name)
-, node()
-{
-    const Scope& sc = GetRequiredScope(element);
-
-    const Element* const Indexes = sc["Indexes"];
-    const Element* const Weights = sc["Weights"];
-
-    const Element& Transform = GetRequiredElement(sc,"Transform",&element);
-    const Element& TransformLink = GetRequiredElement(sc,"TransformLink",&element);
-
-    transform = ReadMatrix(Transform);
-    transformLink = ReadMatrix(TransformLink);
-
-    // it is actually possible that there be Deformer's with no weights
-    if (!!Indexes != !!Weights) {
-        DOMError("either Indexes or Weights are missing from Cluster",&element);
-    }
-
-    if(Indexes) {
-        ParseVectorDataArray(indices,*Indexes);
-        ParseVectorDataArray(weights,*Weights);
-    }
-
-    if(indices.size() != weights.size()) {
-        DOMError("sizes of index and weight array don't match up",&element);
-    }
-
-    // read assigned node
-    const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"Model");
-    for(const Connection* con : conns) {
-        const Model* const mod = ProcessSimpleConnection<Model>(*con, false, "Model -> Cluster", element);
-        if(mod) {
-            node = mod;
-            break;
-        }
-    }
-
-    if (!node) {
-        DOMError("failed to read target Node for Cluster",&element);
-    }
-}
-
-
-// ------------------------------------------------------------------------------------------------
-Cluster::~Cluster()
-{
-
-}
-
-
-// ------------------------------------------------------------------------------------------------
-Skin::Skin(uint64_t id, const Element& element, const Document& doc, const std::string& name)
-: Deformer(id,element,doc,name)
-, accuracy( 0.0f ) {
-    const Scope& sc = GetRequiredScope(element);
-
-    const Element* const Link_DeformAcuracy = sc["Link_DeformAcuracy"];
-    if(Link_DeformAcuracy) {
-        accuracy = ParseTokenAsFloat(GetRequiredToken(*Link_DeformAcuracy,0));
-    }
-
-    // resolve assigned clusters
-    const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"Deformer");
-
-    clusters.reserve(conns.size());
-    for(const Connection* con : conns) {
-
-        const Cluster* const cluster = ProcessSimpleConnection<Cluster>(*con, false, "Cluster -> Skin", element);
-        if(cluster) {
-            clusters.push_back(cluster);
-            continue;
-        }
-    }
-}
-
-
-// ------------------------------------------------------------------------------------------------
-Skin::~Skin()
-{
-
-}
-// ------------------------------------------------------------------------------------------------
-BlendShape::BlendShape(uint64_t id, const Element& element, const Document& doc, const std::string& name)
-    : Deformer(id, element, doc, name)
-{
-    const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(), "Deformer");
-    blendShapeChannels.reserve(conns.size());
-    for (const Connection* con : conns) {
-        const BlendShapeChannel* const bspc = ProcessSimpleConnection<BlendShapeChannel>(*con, false, "BlendShapeChannel -> BlendShape", element);
-        if (bspc) {
-            blendShapeChannels.push_back(bspc);
-            continue;
-        }
-    }
-}
-// ------------------------------------------------------------------------------------------------
-BlendShape::~BlendShape()
-{
-
-}
-// ------------------------------------------------------------------------------------------------
-BlendShapeChannel::BlendShapeChannel(uint64_t id, const Element& element, const Document& doc, const std::string& name)
-    : Deformer(id, element, doc, name)
-{
-    const Scope& sc = GetRequiredScope(element);
-    const Element* const DeformPercent = sc["DeformPercent"];
-    if (DeformPercent) {
-        percent = ParseTokenAsFloat(GetRequiredToken(*DeformPercent, 0));
-    }
-    const Element* const FullWeights = sc["FullWeights"];
-    if (FullWeights) {
-        ParseVectorDataArray(fullWeights, *FullWeights);
-    }
-    const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(), "Geometry");
-    shapeGeometries.reserve(conns.size());
-    for (const Connection* con : conns) {
-        const ShapeGeometry* const sg = ProcessSimpleConnection<ShapeGeometry>(*con, false, "Shape -> BlendShapeChannel", element);
-        if (sg) {
-            shapeGeometries.push_back(sg);
-            continue;
-        }
-    }
-}
-// ------------------------------------------------------------------------------------------------
-BlendShapeChannel::~BlendShapeChannel()
-{
-
-}
-// ------------------------------------------------------------------------------------------------
-}
-}
-#endif
-

+ 0 - 718
thirdparty/assimp/code/FBX/FBXDocument.cpp

@@ -1,718 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the*
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file  FBXDocument.cpp
- *  @brief Implementation of the FBX DOM classes
- */
-
-#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
-
-#include "FBXDocument.h"
-#include "FBXMeshGeometry.h"
-#include "FBXParser.h"
-#include "FBXUtil.h"
-#include "FBXImporter.h"
-#include "FBXImportSettings.h"
-#include "FBXDocumentUtil.h"
-#include "FBXProperties.h"
-
-#include <memory>
-#include <functional>
-#include <map>
-
-namespace Assimp {
-namespace FBX {
-
-using namespace Util;
-
-// ------------------------------------------------------------------------------------------------
-LazyObject::LazyObject(uint64_t id, const Element& element, const Document& doc)
-: doc(doc)
-, element(element)
-, id(id)
-, flags() {
-    // empty
-}
-
-// ------------------------------------------------------------------------------------------------
-LazyObject::~LazyObject()
-{
-    // empty
-}
-
-// ------------------------------------------------------------------------------------------------
-const Object* LazyObject::Get(bool dieOnError)
-{
-    if(IsBeingConstructed() || FailedToConstruct()) {
-        return nullptr;
-    }
-
-    if (object.get()) {
-        return object.get();
-    }
-
-    const Token& key = element.KeyToken();
-    const TokenList& tokens = element.Tokens();
-
-    if(tokens.size() < 3) {
-        DOMError("expected at least 3 tokens: id, name and class tag",&element);
-    }
-
-    const char* err;
-    std::string name = ParseTokenAsString(*tokens[1],err);
-    if (err) {
-        DOMError(err,&element);
-    }
-
-    // small fix for binary reading: binary fbx files don't use
-    // prefixes such as Model:: in front of their names. The
-    // loading code expects this at many places, though!
-    // so convert the binary representation (a 0x0001) to the
-    // double colon notation.
-    if(tokens[1]->IsBinary()) {
-        for (size_t i = 0; i < name.length(); ++i) {
-            if (name[i] == 0x0 && name[i+1] == 0x1) {
-                name = name.substr(i+2) + "::" + name.substr(0,i);
-            }
-        }
-    }
-
-    const std::string classtag = ParseTokenAsString(*tokens[2],err);
-    if (err) {
-        DOMError(err,&element);
-    }
-
-    // prevent recursive calls
-    flags |= BEING_CONSTRUCTED;
-
-    try {
-        // this needs to be relatively fast since it happens a lot,
-        // so avoid constructing strings all the time.
-        const char* obtype = key.begin();
-        const size_t length = static_cast<size_t>(key.end()-key.begin());
-
-        // For debugging
-        //dumpObjectClassInfo( objtype, classtag );
-
-        if (!strncmp(obtype,"Geometry",length)) {
-            if (!strcmp(classtag.c_str(),"Mesh")) {
-                object.reset(new MeshGeometry(id,element,name,doc));
-            }
-            if (!strcmp(classtag.c_str(), "Shape")) {
-                object.reset(new ShapeGeometry(id, element, name, doc));
-            }
-            if (!strcmp(classtag.c_str(), "Line")) {
-                object.reset(new LineGeometry(id, element, name, doc));
-            }
-        }
-        else if (!strncmp(obtype,"NodeAttribute",length)) {
-            if (!strcmp(classtag.c_str(),"Camera")) {
-                object.reset(new Camera(id,element,doc,name));
-            }
-            else if (!strcmp(classtag.c_str(),"CameraSwitcher")) {
-                object.reset(new CameraSwitcher(id,element,doc,name));
-            }
-            else if (!strcmp(classtag.c_str(),"Light")) {
-                object.reset(new Light(id,element,doc,name));
-            }
-            else if (!strcmp(classtag.c_str(),"Null")) {
-                object.reset(new Null(id,element,doc,name));
-            }
-            else if (!strcmp(classtag.c_str(),"LimbNode")) {
-                object.reset(new LimbNode(id,element,doc,name));
-            }
-        }
-        else if (!strncmp(obtype,"Deformer",length)) {
-            if (!strcmp(classtag.c_str(),"Cluster")) {
-                object.reset(new Cluster(id,element,doc,name));
-            }
-            else if (!strcmp(classtag.c_str(),"Skin")) {
-                object.reset(new Skin(id,element,doc,name));
-            }
-            else if (!strcmp(classtag.c_str(), "BlendShape")) {
-                object.reset(new BlendShape(id, element, doc, name));
-            }
-            else if (!strcmp(classtag.c_str(), "BlendShapeChannel")) {
-                object.reset(new BlendShapeChannel(id, element, doc, name));
-            }
-        }
-        else if ( !strncmp( obtype, "Model", length ) ) {
-            // FK and IK effectors are not supported
-            if ( strcmp( classtag.c_str(), "IKEffector" ) && strcmp( classtag.c_str(), "FKEffector" ) ) {
-                object.reset( new Model( id, element, doc, name ) );
-            }
-        }
-        else if (!strncmp(obtype,"Material",length)) {
-            object.reset(new Material(id,element,doc,name));
-        }
-        else if (!strncmp(obtype,"Texture",length)) {
-            object.reset(new Texture(id,element,doc,name));
-        }
-        else if (!strncmp(obtype,"LayeredTexture",length)) {
-            object.reset(new LayeredTexture(id,element,doc,name));
-        }
-        else if (!strncmp(obtype,"Video",length)) {
-            object.reset(new Video(id,element,doc,name));
-        }
-        else if (!strncmp(obtype,"AnimationStack",length)) {
-            object.reset(new AnimationStack(id,element,name,doc));
-        }
-        else if (!strncmp(obtype,"AnimationLayer",length)) {
-            object.reset(new AnimationLayer(id,element,name,doc));
-        }
-        // note: order matters for these two
-        else if (!strncmp(obtype,"AnimationCurve",length)) {
-            object.reset(new AnimationCurve(id,element,name,doc));
-        }
-        else if (!strncmp(obtype,"AnimationCurveNode",length)) {
-            object.reset(new AnimationCurveNode(id,element,name,doc));
-        }
-    }
-    catch(std::exception& ex) {
-        flags &= ~BEING_CONSTRUCTED;
-        flags |= FAILED_TO_CONSTRUCT;
-
-        if(dieOnError || doc.Settings().strictMode) {
-            throw;
-        }
-
-        // note: the error message is already formatted, so raw logging is ok
-        if(!DefaultLogger::isNullLogger()) {
-            ASSIMP_LOG_ERROR(ex.what());
-        }
-        return NULL;
-    }
-
-    if (!object.get()) {
-        //DOMError("failed to convert element to DOM object, class: " + classtag + ", name: " + name,&element);
-    }
-
-    flags &= ~BEING_CONSTRUCTED;
-    return object.get();
-}
-
-// ------------------------------------------------------------------------------------------------
-Object::Object(uint64_t id, const Element& element, const std::string& name)
-: element(element)
-, name(name)
-, id(id)
-{
-    // empty
-}
-
-// ------------------------------------------------------------------------------------------------
-Object::~Object()
-{
-    // empty
-}
-
-// ------------------------------------------------------------------------------------------------
-FileGlobalSettings::FileGlobalSettings(const Document& doc, std::shared_ptr<const PropertyTable> props)
-: props(props)
-, doc(doc)
-{
-    // empty
-}
-
-// ------------------------------------------------------------------------------------------------
-FileGlobalSettings::~FileGlobalSettings()
-{
-    // empty
-}
-
-// ------------------------------------------------------------------------------------------------
-Document::Document(const Parser& parser, const ImportSettings& settings)
-: settings(settings)
-, parser(parser)
-{
-    // Cannot use array default initialization syntax because vc8 fails on it
-    for (auto &timeStamp : creationTimeStamp) {
-        timeStamp = 0;
-    }
-
-    ReadHeader();
-    ReadPropertyTemplates();
-
-    ReadGlobalSettings();
-
-    // This order is important, connections need parsed objects to check
-    // whether connections are ok or not. Objects may not be evaluated yet,
-    // though, since this may require valid connections.
-    ReadObjects();
-    ReadConnections();
-}
-
-// ------------------------------------------------------------------------------------------------
-Document::~Document()
-{
-    for(ObjectMap::value_type& v : objects) {
-        delete v.second;
-    }
-
-    for(ConnectionMap::value_type& v : src_connections) {
-        delete v.second;
-    }
-    // |dest_connections| contain the same Connection objects as the |src_connections|
-}
-
-// ------------------------------------------------------------------------------------------------
-static const unsigned int LowerSupportedVersion = 7100;
-static const unsigned int UpperSupportedVersion = 7400;
-
-void Document::ReadHeader() {
-    // Read ID objects from "Objects" section
-    const Scope& sc = parser.GetRootScope();
-    const Element* const ehead = sc["FBXHeaderExtension"];
-    if(!ehead || !ehead->Compound()) {
-        DOMError("no FBXHeaderExtension dictionary found");
-    }
-
-    const Scope& shead = *ehead->Compound();
-    fbxVersion = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(shead,"FBXVersion",ehead),0));
-
-    // While we may have some success with newer files, we don't support
-    // the older 6.n fbx format
-    if(fbxVersion < LowerSupportedVersion ) {
-        DOMError("unsupported, old format version, supported are only FBX 2011, FBX 2012 and FBX 2013");
-    }
-    if(fbxVersion > UpperSupportedVersion ) {
-        if(Settings().strictMode) {
-            DOMError("unsupported, newer format version, supported are only FBX 2011, FBX 2012 and FBX 2013"
-                " (turn off strict mode to try anyhow) ");
-        }
-        else {
-            DOMWarning("unsupported, newer format version, supported are only FBX 2011, FBX 2012 and FBX 2013,"
-                " trying to read it nevertheless");
-        }
-    }
-
-    const Element* const ecreator = shead["Creator"];
-    if(ecreator) {
-        creator = ParseTokenAsString(GetRequiredToken(*ecreator,0));
-    }
-
-    const Element* const etimestamp = shead["CreationTimeStamp"];
-    if(etimestamp && etimestamp->Compound()) {
-        const Scope& stimestamp = *etimestamp->Compound();
-        creationTimeStamp[0] = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(stimestamp,"Year"),0));
-        creationTimeStamp[1] = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(stimestamp,"Month"),0));
-        creationTimeStamp[2] = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(stimestamp,"Day"),0));
-        creationTimeStamp[3] = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(stimestamp,"Hour"),0));
-        creationTimeStamp[4] = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(stimestamp,"Minute"),0));
-        creationTimeStamp[5] = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(stimestamp,"Second"),0));
-        creationTimeStamp[6] = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(stimestamp,"Millisecond"),0));
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-void Document::ReadGlobalSettings()
-{
-    const Scope& sc = parser.GetRootScope();
-    const Element* const ehead = sc["GlobalSettings"];
-    if ( nullptr == ehead || !ehead->Compound() ) {
-        DOMWarning( "no GlobalSettings dictionary found" );
-        globals.reset(new FileGlobalSettings(*this, std::make_shared<const PropertyTable>()));
-        return;
-    }
-
-    std::shared_ptr<const PropertyTable> props = GetPropertyTable( *this, "", *ehead, *ehead->Compound(), true );
-
-    //double v = PropertyGet<float>( *props.get(), std::string("UnitScaleFactor"), 1.0 );
-
-    if(!props) {
-        DOMError("GlobalSettings dictionary contains no property table");
-    }
-
-    globals.reset(new FileGlobalSettings(*this, props));
-}
-
-// ------------------------------------------------------------------------------------------------
-void Document::ReadObjects()
-{
-    // read ID objects from "Objects" section
-    const Scope& sc = parser.GetRootScope();
-    const Element* const eobjects = sc["Objects"];
-    if(!eobjects || !eobjects->Compound()) {
-        DOMError("no Objects dictionary found");
-    }
-
-    // add a dummy entry to represent the Model::RootNode object (id 0),
-    // which is only indirectly defined in the input file
-    objects[0] = new LazyObject(0L, *eobjects, *this);
-
-    const Scope& sobjects = *eobjects->Compound();
-    for(const ElementMap::value_type& el : sobjects.Elements()) {
-
-        // extract ID
-        const TokenList& tok = el.second->Tokens();
-
-        if (tok.empty()) {
-            DOMError("expected ID after object key",el.second);
-        }
-
-        const char* err;
-        const uint64_t id = ParseTokenAsID(*tok[0], err);
-        if(err) {
-            DOMError(err,el.second);
-        }
-
-        // id=0 is normally implicit
-        if(id == 0L) {
-            DOMError("encountered object with implicitly defined id 0",el.second);
-        }
-
-        if(objects.find(id) != objects.end()) {
-            DOMWarning("encountered duplicate object id, ignoring first occurrence",el.second);
-        }
-
-        objects[id] = new LazyObject(id, *el.second, *this);
-
-        // grab all animation stacks upfront since there is no listing of them
-        if(!strcmp(el.first.c_str(),"AnimationStack")) {
-            animationStacks.push_back(id);
-        }
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-void Document::ReadPropertyTemplates()
-{
-    const Scope& sc = parser.GetRootScope();
-    // read property templates from "Definitions" section
-    const Element* const edefs = sc["Definitions"];
-    if(!edefs || !edefs->Compound()) {
-        DOMWarning("no Definitions dictionary found");
-        return;
-    }
-
-    const Scope& sdefs = *edefs->Compound();
-    const ElementCollection otypes = sdefs.GetCollection("ObjectType");
-    for(ElementMap::const_iterator it = otypes.first; it != otypes.second; ++it) {
-        const Element& el = *(*it).second;
-        const Scope* sc = el.Compound();
-        if(!sc) {
-            DOMWarning("expected nested scope in ObjectType, ignoring",&el);
-            continue;
-        }
-
-        const TokenList& tok = el.Tokens();
-        if(tok.empty()) {
-            DOMWarning("expected name for ObjectType element, ignoring",&el);
-            continue;
-        }
-
-        const std::string& oname = ParseTokenAsString(*tok[0]);
-
-        const ElementCollection templs = sc->GetCollection("PropertyTemplate");
-        for(ElementMap::const_iterator it = templs.first; it != templs.second; ++it) {
-            const Element& el = *(*it).second;
-            const Scope* sc = el.Compound();
-            if(!sc) {
-                DOMWarning("expected nested scope in PropertyTemplate, ignoring",&el);
-                continue;
-            }
-
-            const TokenList& tok = el.Tokens();
-            if(tok.empty()) {
-                DOMWarning("expected name for PropertyTemplate element, ignoring",&el);
-                continue;
-            }
-
-            const std::string& pname = ParseTokenAsString(*tok[0]);
-
-            const Element* Properties70 = (*sc)["Properties70"];
-            if(Properties70) {
-                std::shared_ptr<const PropertyTable> props = std::make_shared<const PropertyTable>(
-                    *Properties70,std::shared_ptr<const PropertyTable>(static_cast<const PropertyTable*>(NULL))
-                );
-
-                templates[oname+"."+pname] = props;
-            }
-        }
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-void Document::ReadConnections()
-{
-    const Scope& sc = parser.GetRootScope();
-    // read property templates from "Definitions" section
-    const Element* const econns = sc["Connections"];
-    if(!econns || !econns->Compound()) {
-        DOMError("no Connections dictionary found");
-    }
-
-    uint64_t insertionOrder = 0l;
-    const Scope& sconns = *econns->Compound();
-    const ElementCollection conns = sconns.GetCollection("C");
-    for(ElementMap::const_iterator it = conns.first; it != conns.second; ++it) {
-        const Element& el = *(*it).second;
-        const std::string& type = ParseTokenAsString(GetRequiredToken(el,0));
-
-        // PP = property-property connection, ignored for now
-        // (tokens: "PP", ID1, "Property1", ID2, "Property2")
-        if ( type == "PP" ) {
-            continue;
-        }
-
-        const uint64_t src = ParseTokenAsID(GetRequiredToken(el,1));
-        const uint64_t dest = ParseTokenAsID(GetRequiredToken(el,2));
-
-        // OO = object-object connection
-        // OP = object-property connection, in which case the destination property follows the object ID
-        const std::string& prop = (type == "OP" ? ParseTokenAsString(GetRequiredToken(el,3)) : "");
-
-        if(objects.find(src) == objects.end()) {
-            DOMWarning("source object for connection does not exist",&el);
-            continue;
-        }
-
-        // dest may be 0 (root node) but we added a dummy object before
-        if(objects.find(dest) == objects.end()) {
-            DOMWarning("destination object for connection does not exist",&el);
-            continue;
-        }
-
-        // add new connection
-        const Connection* const c = new Connection(insertionOrder++,src,dest,prop,*this);
-        src_connections.insert(ConnectionMap::value_type(src,c));
-        dest_connections.insert(ConnectionMap::value_type(dest,c));
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-const std::vector<const AnimationStack*>& Document::AnimationStacks() const
-{
-    if (!animationStacksResolved.empty() || animationStacks.empty()) {
-        return animationStacksResolved;
-    }
-
-    animationStacksResolved.reserve(animationStacks.size());
-    for(uint64_t id : animationStacks) {
-        LazyObject* const lazy = GetObject(id);
-        const AnimationStack* stack;
-        if(!lazy || !(stack = lazy->Get<AnimationStack>())) {
-            DOMWarning("failed to read AnimationStack object");
-            continue;
-        }
-        animationStacksResolved.push_back(stack);
-    }
-
-    return animationStacksResolved;
-}
-
-// ------------------------------------------------------------------------------------------------
-LazyObject* Document::GetObject(uint64_t id) const
-{
-    ObjectMap::const_iterator it = objects.find(id);
-    return it == objects.end() ? nullptr : (*it).second;
-}
-
-#define MAX_CLASSNAMES 6
-
-// ------------------------------------------------------------------------------------------------
-std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, const ConnectionMap& conns) const
-{
-    std::vector<const Connection*> temp;
-
-    const std::pair<ConnectionMap::const_iterator,ConnectionMap::const_iterator> range =
-        conns.equal_range(id);
-
-    temp.reserve(std::distance(range.first,range.second));
-    for (ConnectionMap::const_iterator it = range.first; it != range.second; ++it) {
-        temp.push_back((*it).second);
-    }
-
-    std::sort(temp.begin(), temp.end(), std::mem_fn(&Connection::Compare));
-
-    return temp; // NRVO should handle this
-}
-
-// ------------------------------------------------------------------------------------------------
-std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, bool is_src,
-    const ConnectionMap& conns,
-    const char* const* classnames,
-    size_t count) const
-
-{
-    ai_assert(classnames);
-    ai_assert( count != 0 );
-    ai_assert( count <= MAX_CLASSNAMES);
-
-    size_t lengths[MAX_CLASSNAMES];
-
-    const size_t c = count;
-    for (size_t i = 0; i < c; ++i) {
-        lengths[ i ] = strlen(classnames[i]);
-    }
-
-    std::vector<const Connection*> temp;
-    const std::pair<ConnectionMap::const_iterator,ConnectionMap::const_iterator> range =
-        conns.equal_range(id);
-
-    temp.reserve(std::distance(range.first,range.second));
-    for (ConnectionMap::const_iterator it = range.first; it != range.second; ++it) {
-        const Token& key = (is_src
-            ? (*it).second->LazyDestinationObject()
-            : (*it).second->LazySourceObject()
-        ).GetElement().KeyToken();
-
-        const char* obtype = key.begin();
-
-        for (size_t i = 0; i < c; ++i) {
-            ai_assert(classnames[i]);
-            if(static_cast<size_t>(std::distance(key.begin(),key.end())) == lengths[i] && !strncmp(classnames[i],obtype,lengths[i])) {
-                obtype = nullptr;
-                break;
-            }
-        }
-
-        if(obtype) {
-            continue;
-        }
-
-        temp.push_back((*it).second);
-    }
-
-    std::sort(temp.begin(), temp.end(), std::mem_fn(&Connection::Compare));
-    return temp; // NRVO should handle this
-}
-
-// ------------------------------------------------------------------------------------------------
-std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t source) const
-{
-    return GetConnectionsSequenced(source, ConnectionsBySource());
-}
-
-// ------------------------------------------------------------------------------------------------
-std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t src, const char* classname) const
-{
-    const char* arr[] = {classname};
-    return GetConnectionsBySourceSequenced(src, arr,1);
-}
-
-// ------------------------------------------------------------------------------------------------
-std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t source, 
-        const char* const* classnames, size_t count) const
-{
-    return GetConnectionsSequenced(source, true, ConnectionsBySource(),classnames, count);
-}
-
-// ------------------------------------------------------------------------------------------------
-std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest,
-        const char* classname) const
-{
-    const char* arr[] = {classname};
-    return GetConnectionsByDestinationSequenced(dest, arr,1);
-}
-
-// ------------------------------------------------------------------------------------------------
-std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest) const
-{
-    return GetConnectionsSequenced(dest, ConnectionsByDestination());
-}
-
-// ------------------------------------------------------------------------------------------------
-std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest,
-    const char* const* classnames, size_t count) const
-
-{
-    return GetConnectionsSequenced(dest, false, ConnectionsByDestination(),classnames, count);
-}
-
-// ------------------------------------------------------------------------------------------------
-Connection::Connection(uint64_t insertionOrder,  uint64_t src, uint64_t dest, const std::string& prop,
-        const Document& doc)
-
-: insertionOrder(insertionOrder)
-, prop(prop)
-, src(src)
-, dest(dest)
-, doc(doc)
-{
-    ai_assert(doc.Objects().find(src) != doc.Objects().end());
-    // dest may be 0 (root node)
-    ai_assert(!dest || doc.Objects().find(dest) != doc.Objects().end());
-}
-
-// ------------------------------------------------------------------------------------------------
-Connection::~Connection()
-{
-    // empty
-}
-
-// ------------------------------------------------------------------------------------------------
-LazyObject& Connection::LazySourceObject() const
-{
-    LazyObject* const lazy = doc.GetObject(src);
-    ai_assert(lazy);
-    return *lazy;
-}
-
-// ------------------------------------------------------------------------------------------------
-LazyObject& Connection::LazyDestinationObject() const
-{
-    LazyObject* const lazy = doc.GetObject(dest);
-    ai_assert(lazy);
-    return *lazy;
-}
-
-// ------------------------------------------------------------------------------------------------
-const Object* Connection::SourceObject() const
-{
-    LazyObject* const lazy = doc.GetObject(src);
-    ai_assert(lazy);
-    return lazy->Get();
-}
-
-// ------------------------------------------------------------------------------------------------
-const Object* Connection::DestinationObject() const
-{
-    LazyObject* const lazy = doc.GetObject(dest);
-    ai_assert(lazy);
-    return lazy->Get();
-}
-
-} // !FBX
-} // !Assimp
-
-#endif

+ 0 - 1215
thirdparty/assimp/code/FBX/FBXDocument.h

@@ -1,1215 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file  FBXDocument.h
- *  @brief FBX DOM
- */
-#ifndef INCLUDED_AI_FBX_DOCUMENT_H
-#define INCLUDED_AI_FBX_DOCUMENT_H
-
-#include <numeric>
-#include <stdint.h>
-#include <assimp/mesh.h>
-#include "FBXProperties.h"
-#include "FBXParser.h"
-
-#define _AI_CONCAT(a,b)  a ## b
-#define  AI_CONCAT(a,b)  _AI_CONCAT(a,b)
-
-namespace Assimp {
-namespace FBX {
-
-class Parser;
-class Object;
-struct ImportSettings;
-
-class PropertyTable;
-class Document;
-class Material;
-class ShapeGeometry;
-class LineGeometry;
-class Geometry;
-
-class Video;
-
-class AnimationCurve;
-class AnimationCurveNode;
-class AnimationLayer;
-class AnimationStack;
-
-class BlendShapeChannel;
-class BlendShape;
-class Skin;
-class Cluster;
-
-
-/** Represents a delay-parsed FBX objects. Many objects in the scene
- *  are not needed by assimp, so it makes no sense to parse them
- *  upfront. */
-class LazyObject {
-public:
-    LazyObject(uint64_t id, const Element& element, const Document& doc);
-
-    ~LazyObject();
-
-    const Object* Get(bool dieOnError = false);
-
-    template <typename T>
-    const T* Get(bool dieOnError = false) {
-        const Object* const ob = Get(dieOnError);
-        return ob ? dynamic_cast<const T*>(ob) : NULL;
-    }
-
-    uint64_t ID() const {
-        return id;
-    }
-
-    bool IsBeingConstructed() const {
-        return (flags & BEING_CONSTRUCTED) != 0;
-    }
-
-    bool FailedToConstruct() const {
-        return (flags & FAILED_TO_CONSTRUCT) != 0;
-    }
-
-    const Element& GetElement() const {
-        return element;
-    }
-
-    const Document& GetDocument() const {
-        return doc;
-    }
-
-private:
-    const Document& doc;
-    const Element& element;
-    std::unique_ptr<const Object> object;
-
-    const uint64_t id;
-
-    enum Flags {
-        BEING_CONSTRUCTED = 0x1,
-        FAILED_TO_CONSTRUCT = 0x2
-    };
-
-    unsigned int flags;
-};
-
-/** Base class for in-memory (DOM) representations of FBX objects */
-class Object {
-public:
-    Object(uint64_t id, const Element& element, const std::string& name);
-
-    virtual ~Object();
-
-    const Element& SourceElement() const {
-        return element;
-    }
-
-    const std::string& Name() const {
-        return name;
-    }
-
-    uint64_t ID() const {
-        return id;
-    }
-
-protected:
-    const Element& element;
-    const std::string name;
-    const uint64_t id;
-};
-
-/** DOM class for generic FBX NoteAttribute blocks. NoteAttribute's just hold a property table,
- *  fixed members are added by deriving classes. */
-class NodeAttribute : public Object {
-public:
-    NodeAttribute(uint64_t id, const Element& element, const Document& doc, const std::string& name);
-
-    virtual ~NodeAttribute();
-
-    const PropertyTable& Props() const {
-        ai_assert(props.get());
-        return *props.get();
-    }
-
-private:
-    std::shared_ptr<const PropertyTable> props;
-};
-
-/** DOM base class for FBX camera settings attached to a node */
-class CameraSwitcher : public NodeAttribute {
-public:
-    CameraSwitcher(uint64_t id, const Element& element, const Document& doc, const std::string& name);
-
-    virtual ~CameraSwitcher();
-
-    int CameraID() const {
-        return cameraId;
-    }
-
-    const std::string& CameraName() const {
-        return cameraName;
-    }
-
-    const std::string& CameraIndexName() const {
-        return cameraIndexName;
-    }
-
-private:
-    int cameraId;
-    std::string cameraName;
-    std::string cameraIndexName;
-};
-
-#define fbx_stringize(a) #a
-
-#define fbx_simple_property(name, type, default_value) \
-    type name() const { \
-        return PropertyGet<type>(Props(), fbx_stringize(name), (default_value)); \
-    }
-
-// XXX improve logging
-#define fbx_simple_enum_property(name, type, default_value) \
-    type name() const { \
-        const int ival = PropertyGet<int>(Props(), fbx_stringize(name), static_cast<int>(default_value)); \
-        if (ival < 0 || ival >= AI_CONCAT(type, _MAX)) { \
-            ai_assert(static_cast<int>(default_value) >= 0 && static_cast<int>(default_value) < AI_CONCAT(type, _MAX)); \
-            return static_cast<type>(default_value); \
-        } \
-        return static_cast<type>(ival); \
-}
-
-
-/** DOM base class for FBX cameras attached to a node */
-class Camera : public NodeAttribute {
-public:
-    Camera(uint64_t id, const Element& element, const Document& doc, const std::string& name);
-
-    virtual  ~Camera();
-
-    fbx_simple_property(Position, aiVector3D, aiVector3D(0,0,0))
-    fbx_simple_property(UpVector, aiVector3D, aiVector3D(0,1,0))
-    fbx_simple_property(InterestPosition, aiVector3D, aiVector3D(0,0,0))
-
-    fbx_simple_property(AspectWidth, float, 1.0f)
-    fbx_simple_property(AspectHeight, float, 1.0f)
-    fbx_simple_property(FilmWidth, float, 1.0f)
-    fbx_simple_property(FilmHeight, float, 1.0f)
-
-    fbx_simple_property(NearPlane, float, 0.1f)
-    fbx_simple_property(FarPlane, float, 100.0f)
-
-    fbx_simple_property(FilmAspectRatio, float, 1.0f)
-    fbx_simple_property(ApertureMode, int, 0)
-
-    fbx_simple_property(FieldOfView, float, 1.0f)
-    fbx_simple_property(FocalLength, float, 1.0f)
-};
-
-/** DOM base class for FBX null markers attached to a node */
-class Null : public NodeAttribute {
-public:
-    Null(uint64_t id, const Element& element, const Document& doc, const std::string& name);
-    virtual ~Null();
-};
-
-/** DOM base class for FBX limb node markers attached to a node */
-class LimbNode : public NodeAttribute {
-public:
-    LimbNode(uint64_t id, const Element& element, const Document& doc, const std::string& name);
-    virtual ~LimbNode();
-};
-
-/** DOM base class for FBX lights attached to a node */
-class Light : public NodeAttribute {
-public:
-    Light(uint64_t id, const Element& element, const Document& doc, const std::string& name);
-    virtual ~Light();
-
-    enum Type
-    {
-        Type_Point,
-        Type_Directional,
-        Type_Spot,
-        Type_Area,
-        Type_Volume,
-
-        Type_MAX // end-of-enum sentinel
-    };
-
-    enum Decay
-    {
-        Decay_None,
-        Decay_Linear,
-        Decay_Quadratic,
-        Decay_Cubic,
-
-        Decay_MAX // end-of-enum sentinel
-    };
-
-    fbx_simple_property(Color, aiVector3D, aiVector3D(1,1,1))
-    fbx_simple_enum_property(LightType, Type, 0)
-    fbx_simple_property(CastLightOnObject, bool, false)
-    fbx_simple_property(DrawVolumetricLight, bool, true)
-    fbx_simple_property(DrawGroundProjection, bool, true)
-    fbx_simple_property(DrawFrontFacingVolumetricLight, bool, false)
-    fbx_simple_property(Intensity, float, 100.0f)
-    fbx_simple_property(InnerAngle, float, 0.0f)
-    fbx_simple_property(OuterAngle, float, 45.0f)
-    fbx_simple_property(Fog, int, 50)
-    fbx_simple_enum_property(DecayType, Decay, 2)
-    fbx_simple_property(DecayStart, float, 1.0f)
-    fbx_simple_property(FileName, std::string, "")
-
-    fbx_simple_property(EnableNearAttenuation, bool, false)
-    fbx_simple_property(NearAttenuationStart, float, 0.0f)
-    fbx_simple_property(NearAttenuationEnd, float, 0.0f)
-    fbx_simple_property(EnableFarAttenuation, bool, false)
-    fbx_simple_property(FarAttenuationStart, float, 0.0f)
-    fbx_simple_property(FarAttenuationEnd, float, 0.0f)
-
-    fbx_simple_property(CastShadows, bool, true)
-    fbx_simple_property(ShadowColor, aiVector3D, aiVector3D(0,0,0))
-
-    fbx_simple_property(AreaLightShape, int, 0)
-
-    fbx_simple_property(LeftBarnDoor, float, 20.0f)
-    fbx_simple_property(RightBarnDoor, float, 20.0f)
-    fbx_simple_property(TopBarnDoor, float, 20.0f)
-    fbx_simple_property(BottomBarnDoor, float, 20.0f)
-    fbx_simple_property(EnableBarnDoor, bool, true)
-};
-
-/** DOM base class for FBX models (even though its semantics are more "node" than "model" */
-class Model : public Object {
-public:
-    enum RotOrder {
-        RotOrder_EulerXYZ = 0,
-        RotOrder_EulerXZY,
-        RotOrder_EulerYZX,
-        RotOrder_EulerYXZ,
-        RotOrder_EulerZXY,
-        RotOrder_EulerZYX,
-
-        RotOrder_SphericXYZ,
-
-        RotOrder_MAX // end-of-enum sentinel
-    };
-
-    enum TransformInheritance {
-        TransformInheritance_RrSs = 0,
-        TransformInheritance_RSrs,
-        TransformInheritance_Rrs,
-
-        TransformInheritance_MAX // end-of-enum sentinel
-    };
-
-    Model(uint64_t id, const Element& element, const Document& doc, const std::string& name);
-
-    virtual ~Model();
-
-    fbx_simple_property(QuaternionInterpolate, int, 0)
-
-    fbx_simple_property(RotationOffset, aiVector3D, aiVector3D())
-    fbx_simple_property(RotationPivot, aiVector3D, aiVector3D())
-    fbx_simple_property(ScalingOffset, aiVector3D, aiVector3D())
-    fbx_simple_property(ScalingPivot, aiVector3D, aiVector3D())
-    fbx_simple_property(TranslationActive, bool, false)
-
-    fbx_simple_property(TranslationMin, aiVector3D, aiVector3D())
-    fbx_simple_property(TranslationMax, aiVector3D, aiVector3D())
-
-    fbx_simple_property(TranslationMinX, bool, false)
-    fbx_simple_property(TranslationMaxX, bool, false)
-    fbx_simple_property(TranslationMinY, bool, false)
-    fbx_simple_property(TranslationMaxY, bool, false)
-    fbx_simple_property(TranslationMinZ, bool, false)
-    fbx_simple_property(TranslationMaxZ, bool, false)
-
-    fbx_simple_enum_property(RotationOrder, RotOrder, 0)
-    fbx_simple_property(RotationSpaceForLimitOnly, bool, false)
-    fbx_simple_property(RotationStiffnessX, float, 0.0f)
-    fbx_simple_property(RotationStiffnessY, float, 0.0f)
-    fbx_simple_property(RotationStiffnessZ, float, 0.0f)
-    fbx_simple_property(AxisLen, float, 0.0f)
-
-    fbx_simple_property(PreRotation, aiVector3D, aiVector3D())
-    fbx_simple_property(PostRotation, aiVector3D, aiVector3D())
-    fbx_simple_property(RotationActive, bool, false)
-
-    fbx_simple_property(RotationMin, aiVector3D, aiVector3D())
-    fbx_simple_property(RotationMax, aiVector3D, aiVector3D())
-
-    fbx_simple_property(RotationMinX, bool, false)
-    fbx_simple_property(RotationMaxX, bool, false)
-    fbx_simple_property(RotationMinY, bool, false)
-    fbx_simple_property(RotationMaxY, bool, false)
-    fbx_simple_property(RotationMinZ, bool, false)
-    fbx_simple_property(RotationMaxZ, bool, false)
-    fbx_simple_enum_property(InheritType, TransformInheritance, 0)
-
-    fbx_simple_property(ScalingActive, bool, false)
-    fbx_simple_property(ScalingMin, aiVector3D, aiVector3D())
-    fbx_simple_property(ScalingMax, aiVector3D, aiVector3D(1.f,1.f,1.f))
-    fbx_simple_property(ScalingMinX, bool, false)
-    fbx_simple_property(ScalingMaxX, bool, false)
-    fbx_simple_property(ScalingMinY, bool, false)
-    fbx_simple_property(ScalingMaxY, bool, false)
-    fbx_simple_property(ScalingMinZ, bool, false)
-    fbx_simple_property(ScalingMaxZ, bool, false)
-
-    fbx_simple_property(GeometricTranslation, aiVector3D, aiVector3D())
-    fbx_simple_property(GeometricRotation, aiVector3D, aiVector3D())
-    fbx_simple_property(GeometricScaling, aiVector3D, aiVector3D(1.f, 1.f, 1.f))
-
-    fbx_simple_property(MinDampRangeX, float, 0.0f)
-    fbx_simple_property(MinDampRangeY, float, 0.0f)
-    fbx_simple_property(MinDampRangeZ, float, 0.0f)
-    fbx_simple_property(MaxDampRangeX, float, 0.0f)
-    fbx_simple_property(MaxDampRangeY, float, 0.0f)
-    fbx_simple_property(MaxDampRangeZ, float, 0.0f)
-
-    fbx_simple_property(MinDampStrengthX, float, 0.0f)
-    fbx_simple_property(MinDampStrengthY, float, 0.0f)
-    fbx_simple_property(MinDampStrengthZ, float, 0.0f)
-    fbx_simple_property(MaxDampStrengthX, float, 0.0f)
-    fbx_simple_property(MaxDampStrengthY, float, 0.0f)
-    fbx_simple_property(MaxDampStrengthZ, float, 0.0f)
-
-    fbx_simple_property(PreferredAngleX, float, 0.0f)
-    fbx_simple_property(PreferredAngleY, float, 0.0f)
-    fbx_simple_property(PreferredAngleZ, float, 0.0f)
-
-    fbx_simple_property(Show, bool, true)
-    fbx_simple_property(LODBox, bool, false)
-    fbx_simple_property(Freeze, bool, false)
-
-    const std::string& Shading() const {
-        return shading;
-    }
-
-    const std::string& Culling() const {
-        return culling;
-    }
-
-    const PropertyTable& Props() const {
-        ai_assert(props.get());
-        return *props.get();
-    }
-
-    /** Get material links */
-    const std::vector<const Material*>& GetMaterials() const {
-        return materials;
-    }
-
-    /** Get geometry links */
-    const std::vector<const Geometry*>& GetGeometry() const {
-        return geometry;
-    }
-
-    /** Get node attachments */
-    const std::vector<const NodeAttribute*>& GetAttributes() const {
-        return attributes;
-    }
-
-    /** convenience method to check if the node has a Null node marker */
-    bool IsNull() const;
-
-private:
-    void ResolveLinks(const Element& element, const Document& doc);
-
-private:
-    std::vector<const Material*> materials;
-    std::vector<const Geometry*> geometry;
-    std::vector<const NodeAttribute*> attributes;
-
-    std::string shading;
-    std::string culling;
-    std::shared_ptr<const PropertyTable> props;
-};
-
-/** DOM class for generic FBX textures */
-class Texture : public Object {
-public:
-    Texture(uint64_t id, const Element& element, const Document& doc, const std::string& name);
-
-    virtual ~Texture();
-
-    const std::string& Type() const {
-        return type;
-    }
-
-    const std::string& FileName() const {
-        return fileName;
-    }
-
-    const std::string& RelativeFilename() const {
-        return relativeFileName;
-    }
-
-    const std::string& AlphaSource() const {
-        return alphaSource;
-    }
-
-    const aiVector2D& UVTranslation() const {
-        return uvTrans;
-    }
-
-    const aiVector2D& UVScaling() const {
-        return uvScaling;
-    }
-
-    const PropertyTable& Props() const {
-        ai_assert(props.get());
-        return *props.get();
-    }
-
-    // return a 4-tuple
-    const unsigned int* Crop() const {
-        return crop;
-    }
-
-    const Video* Media() const {
-        return media;
-    }
-
-private:
-    aiVector2D uvTrans;
-    aiVector2D uvScaling;
-
-    std::string type;
-    std::string relativeFileName;
-    std::string fileName;
-    std::string alphaSource;
-    std::shared_ptr<const PropertyTable> props;
-
-    unsigned int crop[4];
-
-    const Video* media;
-};
-
-/** DOM class for layered FBX textures */
-class LayeredTexture : public Object {
-public:
-    LayeredTexture(uint64_t id, const Element& element, const Document& doc, const std::string& name);
-    virtual ~LayeredTexture();
-
-    // Can only be called after construction of the layered texture object due to construction flag.
-    void fillTexture(const Document& doc);
-
-    enum BlendMode {
-        BlendMode_Translucent,
-        BlendMode_Additive,
-        BlendMode_Modulate,
-        BlendMode_Modulate2,
-        BlendMode_Over,
-        BlendMode_Normal,
-        BlendMode_Dissolve,
-        BlendMode_Darken,
-        BlendMode_ColorBurn,
-        BlendMode_LinearBurn,
-        BlendMode_DarkerColor,
-        BlendMode_Lighten,
-        BlendMode_Screen,
-        BlendMode_ColorDodge,
-        BlendMode_LinearDodge,
-        BlendMode_LighterColor,
-        BlendMode_SoftLight,
-        BlendMode_HardLight,
-        BlendMode_VividLight,
-        BlendMode_LinearLight,
-        BlendMode_PinLight,
-        BlendMode_HardMix,
-        BlendMode_Difference,
-        BlendMode_Exclusion,
-        BlendMode_Subtract,
-        BlendMode_Divide,
-        BlendMode_Hue,
-        BlendMode_Saturation,
-        BlendMode_Color,
-        BlendMode_Luminosity,
-        BlendMode_Overlay,
-        BlendMode_BlendModeCount
-    };
-
-    const Texture* getTexture(int index=0) const
-    {
-		return textures[index];
-
-    }
-	int textureCount() const {
-		return static_cast<int>(textures.size());
-	}
-    BlendMode GetBlendMode() const
-    {
-        return blendMode;
-    }
-    float Alpha()
-    {
-        return alpha;
-    }
-private:
-	std::vector<const Texture*> textures;
-    BlendMode blendMode;
-    float alpha;
-};
-
-typedef std::fbx_unordered_map<std::string, const Texture*> TextureMap;
-typedef std::fbx_unordered_map<std::string, const LayeredTexture*> LayeredTextureMap;
-
-
-/** DOM class for generic FBX videos */
-class Video : public Object {
-public:
-    Video(uint64_t id, const Element& element, const Document& doc, const std::string& name);
-
-    virtual ~Video();
-
-    const std::string& Type() const {
-        return type;
-    }
-
-    const std::string& FileName() const {
-        return fileName;
-    }
-
-    const std::string& RelativeFilename() const {
-        return relativeFileName;
-    }
-
-    const PropertyTable& Props() const {
-        ai_assert(props.get());
-        return *props.get();
-    }
-
-    const uint8_t* Content() const {
-        ai_assert(content);
-        return content;
-    }
-
-    uint64_t ContentLength() const {
-        return contentLength;
-    }
-
-    uint8_t* RelinquishContent() {
-        uint8_t* ptr = content;
-        content = 0;
-        return ptr;
-    }
-
-    bool operator==(const Video& other) const
-    {
-        return (
-               type == other.type
-            && relativeFileName == other.relativeFileName
-            && fileName == other.fileName
-        );
-    }
-
-    bool operator<(const Video& other) const
-    {
-        return std::tie(type, relativeFileName, fileName) < std::tie(other.type, other.relativeFileName, other.fileName);
-    }
-
-private:
-    std::string type;
-    std::string relativeFileName;
-    std::string fileName;
-    std::shared_ptr<const PropertyTable> props;
-
-    uint64_t contentLength;
-    uint8_t* content;
-};
-
-/** DOM class for generic FBX materials */
-class Material : public Object {
-public:
-    Material(uint64_t id, const Element& element, const Document& doc, const std::string& name);
-
-    virtual ~Material();
-
-    const std::string& GetShadingModel() const {
-        return shading;
-    }
-
-    bool IsMultilayer() const {
-        return multilayer;
-    }
-
-    const PropertyTable& Props() const {
-        ai_assert(props.get());
-        return *props.get();
-    }
-
-    const TextureMap& Textures() const {
-        return textures;
-    }
-
-    const LayeredTextureMap& LayeredTextures() const {
-        return layeredTextures;
-    }
-
-private:
-    std::string shading;
-    bool multilayer;
-    std::shared_ptr<const PropertyTable> props;
-
-    TextureMap textures;
-    LayeredTextureMap layeredTextures;
-};
-
-typedef std::vector<int64_t> KeyTimeList;
-typedef std::vector<float> KeyValueList;
-
-/** Represents a FBX animation curve (i.e. a 1-dimensional set of keyframes and values therefor) */
-class AnimationCurve : public Object {
-public:
-    AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& doc);
-    virtual ~AnimationCurve();
-
-    /** get list of keyframe positions (time).
-     *  Invariant: |GetKeys()| > 0 */
-    const KeyTimeList& GetKeys() const {
-        return keys;
-    }
-
-    /** get list of keyframe values.
-      * Invariant: |GetKeys()| == |GetValues()| && |GetKeys()| > 0*/
-    const KeyValueList& GetValues() const {
-        return values;
-    }
-
-    const std::vector<float>& GetAttributes() const {
-        return attributes;
-    }
-
-    const std::vector<unsigned int>& GetFlags() const {
-        return flags;
-    }
-
-private:
-    KeyTimeList keys;
-    KeyValueList values;
-    std::vector<float> attributes;
-    std::vector<unsigned int> flags;
-};
-
-// property-name -> animation curve
-typedef std::map<std::string, const AnimationCurve*> AnimationCurveMap;
-
-/** Represents a FBX animation curve (i.e. a mapping from single animation curves to nodes) */
-class AnimationCurveNode : public Object {
-public:
-    /* the optional white list specifies a list of property names for which the caller
-    wants animations for. If the curve node does not match one of these, std::range_error
-    will be thrown. */
-    AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, const Document& doc,
-        const char* const * target_prop_whitelist = NULL, size_t whitelist_size = 0);
-
-    virtual ~AnimationCurveNode();
-
-    const PropertyTable& Props() const {
-        ai_assert(props.get());
-        return *props.get();
-    }
-
-
-    const AnimationCurveMap& Curves() const;
-
-    /** Object the curve is assigned to, this can be NULL if the
-     *  target object has no DOM representation or could not
-     *  be read for other reasons.*/
-    const Object* Target() const {
-        return target;
-    }
-
-    const Model* TargetAsModel() const {
-        return dynamic_cast<const Model*>(target);
-    }
-
-    const NodeAttribute* TargetAsNodeAttribute() const {
-        return dynamic_cast<const NodeAttribute*>(target);
-    }
-
-    /** Property of Target() that is being animated*/
-    const std::string& TargetProperty() const {
-        return prop;
-    }
-
-private:
-    const Object* target;
-    std::shared_ptr<const PropertyTable> props;
-    mutable AnimationCurveMap curves;
-
-    std::string prop;
-    const Document& doc;
-};
-
-typedef std::vector<const AnimationCurveNode*> AnimationCurveNodeList;
-
-/** Represents a FBX animation layer (i.e. a list of node animations) */
-class AnimationLayer : public Object {
-public:
-    AnimationLayer(uint64_t id, const Element& element, const std::string& name, const Document& doc);
-    virtual ~AnimationLayer();
-
-    const PropertyTable& Props() const {
-        ai_assert(props.get());
-        return *props.get();
-    }
-
-    /* the optional white list specifies a list of property names for which the caller
-    wants animations for. Curves not matching this list will not be added to the
-    animation layer. */
-    AnimationCurveNodeList Nodes(const char* const * target_prop_whitelist = nullptr, size_t whitelist_size = 0) const;
-
-private:
-    std::shared_ptr<const PropertyTable> props;
-    const Document& doc;
-};
-
-typedef std::vector<const AnimationLayer*> AnimationLayerList;
-
-/** Represents a FBX animation stack (i.e. a list of animation layers) */
-class AnimationStack : public Object {
-public:
-    AnimationStack(uint64_t id, const Element& element, const std::string& name, const Document& doc);
-    virtual ~AnimationStack();
-
-    fbx_simple_property(LocalStart, int64_t, 0L)
-    fbx_simple_property(LocalStop, int64_t, 0L)
-    fbx_simple_property(ReferenceStart, int64_t, 0L)
-    fbx_simple_property(ReferenceStop, int64_t, 0L)
-
-    const PropertyTable& Props() const {
-        ai_assert(props.get());
-        return *props.get();
-    }
-
-    const AnimationLayerList& Layers() const {
-        return layers;
-    }
-
-private:
-    std::shared_ptr<const PropertyTable> props;
-    AnimationLayerList layers;
-};
-
-
-/** DOM class for deformers */
-class Deformer : public Object {
-public:
-    Deformer(uint64_t id, const Element& element, const Document& doc, const std::string& name);
-    virtual ~Deformer();
-
-    const PropertyTable& Props() const {
-        ai_assert(props.get());
-        return *props.get();
-    }
-
-private:
-    std::shared_ptr<const PropertyTable> props;
-};
-
-typedef std::vector<float> WeightArray;
-typedef std::vector<unsigned int> WeightIndexArray;
-
-
-/** DOM class for BlendShapeChannel deformers */
-class BlendShapeChannel : public Deformer {
-public:
-    BlendShapeChannel(uint64_t id, const Element& element, const Document& doc, const std::string& name);
-
-    virtual ~BlendShapeChannel();
-
-    float DeformPercent() const {
-        return percent;
-    }
-
-    const WeightArray& GetFullWeights() const {
-        return fullWeights;
-    }
-
-    const std::vector<const ShapeGeometry*>& GetShapeGeometries() const {
-        return shapeGeometries;
-    }
-
-private:
-    float percent;
-    WeightArray fullWeights;
-    std::vector<const ShapeGeometry*> shapeGeometries;
-};
-
-/** DOM class for BlendShape deformers */
-class BlendShape : public Deformer {
-public:
-    BlendShape(uint64_t id, const Element& element, const Document& doc, const std::string& name);
-
-    virtual ~BlendShape();
-
-    const std::vector<const BlendShapeChannel*>& BlendShapeChannels() const {
-        return blendShapeChannels;
-    }
-
-private:
-    std::vector<const BlendShapeChannel*> blendShapeChannels;
-};
-
-/** DOM class for skin deformer clusters (aka sub-deformers) */
-class Cluster : public Deformer {
-public:
-    Cluster(uint64_t id, const Element& element, const Document& doc, const std::string& name);
-
-    virtual ~Cluster();
-
-    /** get the list of deformer weights associated with this cluster.
-     *  Use #GetIndices() to get the associated vertices. Both arrays
-     *  have the same size (and may also be empty). */
-    const WeightArray& GetWeights() const {
-        return weights;
-    }
-
-    /** get indices into the vertex data of the geometry associated
-     *  with this cluster. Use #GetWeights() to get the associated weights.
-     *  Both arrays have the same size (and may also be empty). */
-    const WeightIndexArray& GetIndices() const {
-        return indices;
-    }
-
-    /** */
-    const aiMatrix4x4& Transform() const {
-        return transform;
-    }
-
-    const aiMatrix4x4& TransformLink() const {
-        return transformLink;
-    }
-
-    const Model* TargetNode() const {
-        return node;
-    }
-
-private:
-    WeightArray weights;
-    WeightIndexArray indices;
-
-    aiMatrix4x4 transform;
-    aiMatrix4x4 transformLink;
-
-    const Model* node;
-};
-
-/** DOM class for skin deformers */
-class Skin : public Deformer {
-public:
-    Skin(uint64_t id, const Element& element, const Document& doc, const std::string& name);
-
-    virtual ~Skin();
-
-    float DeformAccuracy() const {
-        return accuracy;
-    }
-
-    const std::vector<const Cluster*>& Clusters() const {
-        return clusters;
-    }
-
-private:
-    float accuracy;
-    std::vector<const Cluster*> clusters;
-};
-
-/** Represents a link between two FBX objects. */
-class Connection {
-public:
-    Connection(uint64_t insertionOrder,  uint64_t src, uint64_t dest, const std::string& prop, const Document& doc);
-
-    ~Connection();
-
-    // note: a connection ensures that the source and dest objects exist, but
-    // not that they have DOM representations, so the return value of one of
-    // these functions can still be NULL.
-    const Object* SourceObject() const;
-    const Object* DestinationObject() const;
-
-    // these, however, are always guaranteed to be valid
-    LazyObject& LazySourceObject() const;
-    LazyObject& LazyDestinationObject() const;
-
-
-    /** return the name of the property the connection is attached to.
-      * this is an empty string for object to object (OO) connections. */
-    const std::string& PropertyName() const {
-        return prop;
-    }
-
-    uint64_t InsertionOrder() const {
-        return insertionOrder;
-    }
-
-    int CompareTo(const Connection* c) const {
-        ai_assert( nullptr != c );
-
-        // note: can't subtract because this would overflow uint64_t
-        if(InsertionOrder() > c->InsertionOrder()) {
-            return 1;
-        }
-        else if(InsertionOrder() < c->InsertionOrder()) {
-            return -1;
-        }
-        return 0;
-    }
-
-    bool Compare(const Connection* c) const {
-        ai_assert( nullptr != c );
-
-        return InsertionOrder() < c->InsertionOrder();
-    }
-
-public:
-    uint64_t insertionOrder;
-    const std::string prop;
-
-    uint64_t src, dest;
-    const Document& doc;
-};
-
-// XXX again, unique_ptr would be useful. shared_ptr is too
-// bloated since the objects have a well-defined single owner
-// during their entire lifetime (Document). FBX files have
-// up to many thousands of objects (most of which we never use),
-// so the memory overhead for them should be kept at a minimum.
-typedef std::fbx_unordered_map<uint64_t, LazyObject*> ObjectMap;
-typedef std::fbx_unordered_map<std::string, std::shared_ptr<const PropertyTable> > PropertyTemplateMap;
-
-typedef std::fbx_unordered_multimap<uint64_t, const Connection*> ConnectionMap;
-
-/** DOM class for global document settings, a single instance per document can
- *  be accessed via Document.Globals(). */
-class FileGlobalSettings {
-public:
-    FileGlobalSettings(const Document& doc, std::shared_ptr<const PropertyTable> props);
-
-    ~FileGlobalSettings();
-
-    const PropertyTable& Props() const {
-        ai_assert(props.get());
-        return *props.get();
-    }
-
-    const Document& GetDocument() const {
-        return doc;
-    }
-
-    fbx_simple_property(UpAxis, int, 1)
-    fbx_simple_property(UpAxisSign, int, 1)
-    fbx_simple_property(FrontAxis, int, 2)
-    fbx_simple_property(FrontAxisSign, int, 1)
-    fbx_simple_property(CoordAxis, int, 0)
-    fbx_simple_property(CoordAxisSign, int, 1)
-    fbx_simple_property(OriginalUpAxis, int, 0)
-    fbx_simple_property(OriginalUpAxisSign, int, 1)
-    fbx_simple_property(UnitScaleFactor, float, 1)
-    fbx_simple_property(OriginalUnitScaleFactor, float, 1)
-    fbx_simple_property(AmbientColor, aiVector3D, aiVector3D(0,0,0))
-    fbx_simple_property(DefaultCamera, std::string, "")
-
-
-    enum FrameRate {
-        FrameRate_DEFAULT = 0,
-        FrameRate_120 = 1,
-        FrameRate_100 = 2,
-        FrameRate_60 = 3,
-        FrameRate_50 = 4,
-        FrameRate_48 = 5,
-        FrameRate_30 = 6,
-        FrameRate_30_DROP = 7,
-        FrameRate_NTSC_DROP_FRAME = 8,
-        FrameRate_NTSC_FULL_FRAME = 9,
-        FrameRate_PAL = 10,
-        FrameRate_CINEMA = 11,
-        FrameRate_1000 = 12,
-        FrameRate_CINEMA_ND = 13,
-        FrameRate_CUSTOM = 14,
-
-        FrameRate_MAX// end-of-enum sentinel
-    };
-
-    fbx_simple_enum_property(TimeMode, FrameRate, FrameRate_DEFAULT)
-    fbx_simple_property(TimeSpanStart, uint64_t, 0L)
-    fbx_simple_property(TimeSpanStop, uint64_t, 0L)
-    fbx_simple_property(CustomFrameRate, float, -1.0f)
-
-private:
-    std::shared_ptr<const PropertyTable> props;
-    const Document& doc;
-};
-
-/** DOM root for a FBX file */
-class Document {
-public:
-    Document(const Parser& parser, const ImportSettings& settings);
-
-    ~Document();
-
-    LazyObject* GetObject(uint64_t id) const;
-
-    bool IsBinary() const {
-        return parser.IsBinary();
-    }
-
-    unsigned int FBXVersion() const {
-        return fbxVersion;
-    }
-
-    const std::string& Creator() const {
-        return creator;
-    }
-
-    // elements (in this order): Year, Month, Day, Hour, Second, Millisecond
-    const unsigned int* CreationTimeStamp() const {
-        return creationTimeStamp;
-    }
-
-    const FileGlobalSettings& GlobalSettings() const {
-        ai_assert(globals.get());
-        return *globals.get();
-    }
-
-    const PropertyTemplateMap& Templates() const {
-        return templates;
-    }
-
-    const ObjectMap& Objects() const {
-        return objects;
-    }
-
-    const ImportSettings& Settings() const {
-        return settings;
-    }
-
-    const ConnectionMap& ConnectionsBySource() const {
-        return src_connections;
-    }
-
-    const ConnectionMap& ConnectionsByDestination() const {
-        return dest_connections;
-    }
-
-    // note: the implicit rule in all DOM classes is to always resolve
-    // from destination to source (since the FBX object hierarchy is,
-    // with very few exceptions, a DAG, this avoids cycles). In all
-    // cases that may involve back-facing edges in the object graph,
-    // use LazyObject::IsBeingConstructed() to check.
-
-    std::vector<const Connection*> GetConnectionsBySourceSequenced(uint64_t source) const;
-    std::vector<const Connection*> GetConnectionsByDestinationSequenced(uint64_t dest) const;
-
-    std::vector<const Connection*> GetConnectionsBySourceSequenced(uint64_t source, const char* classname) const;
-    std::vector<const Connection*> GetConnectionsByDestinationSequenced(uint64_t dest, const char* classname) const;
-
-    std::vector<const Connection*> GetConnectionsBySourceSequenced(uint64_t source,
-        const char* const* classnames, size_t count) const;
-    std::vector<const Connection*> GetConnectionsByDestinationSequenced(uint64_t dest,
-        const char* const* classnames,
-        size_t count) const;
-
-    const std::vector<const AnimationStack*>& AnimationStacks() const;
-
-private:
-    std::vector<const Connection*> GetConnectionsSequenced(uint64_t id, const ConnectionMap&) const;
-    std::vector<const Connection*> GetConnectionsSequenced(uint64_t id, bool is_src,
-        const ConnectionMap&,
-        const char* const* classnames,
-        size_t count) const;
-    void ReadHeader();
-    void ReadObjects();
-    void ReadPropertyTemplates();
-    void ReadConnections();
-    void ReadGlobalSettings();
-
-private:
-    const ImportSettings& settings;
-
-    ObjectMap objects;
-    const Parser& parser;
-
-    PropertyTemplateMap templates;
-    ConnectionMap src_connections;
-    ConnectionMap dest_connections;
-
-    unsigned int fbxVersion;
-    std::string creator;
-    unsigned int creationTimeStamp[7];
-
-    std::vector<uint64_t> animationStacks;
-    mutable std::vector<const AnimationStack*> animationStacksResolved;
-
-    std::unique_ptr<FileGlobalSettings> globals;
-};
-
-} // Namespace FBX
-} // Namespace Assimp
-
-namespace std
-{
-    template <>
-    struct hash<const Assimp::FBX::Video>
-    {
-        std::size_t operator()(const Assimp::FBX::Video& video) const
-        {
-            using std::size_t;
-            using std::hash;
-            using std::string;
-
-            size_t res = 17;
-            res = res * 31 + hash<string>()(video.Name());
-            res = res * 31 + hash<string>()(video.RelativeFilename());
-            res = res * 31 + hash<string>()(video.Type());
-
-            return res;
-        }
-    };
-}
-
-#endif // INCLUDED_AI_FBX_DOCUMENT_H

+ 0 - 135
thirdparty/assimp/code/FBX/FBXDocumentUtil.cpp

@@ -1,135 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file  FBXDocumentUtil.cpp
- *  @brief Implementation of the FBX DOM utility functions declared in FBXDocumentUtil.h
- */
-
-#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
-
-#include "FBXParser.h"
-#include "FBXDocument.h"
-#include "FBXUtil.h"
-#include "FBXDocumentUtil.h"
-#include "FBXProperties.h"
-
-
-namespace Assimp {
-namespace FBX {
-namespace Util {
-
-// ------------------------------------------------------------------------------------------------
-// signal DOM construction error, this is always unrecoverable. Throws DeadlyImportError.
-void DOMError(const std::string& message, const Token& token)
-{
-    throw DeadlyImportError(Util::AddTokenText("FBX-DOM",message,&token));
-}
-
-// ------------------------------------------------------------------------------------------------
-void DOMError(const std::string& message, const Element* element /*= NULL*/)
-{
-    if(element) {
-        DOMError(message,element->KeyToken());
-    }
-    throw DeadlyImportError("FBX-DOM " + message);
-}
-
-
-// ------------------------------------------------------------------------------------------------
-// print warning, do return
-void DOMWarning(const std::string& message, const Token& token)
-{
-    if(DefaultLogger::get()) {
-        ASSIMP_LOG_WARN(Util::AddTokenText("FBX-DOM",message,&token));
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-void DOMWarning(const std::string& message, const Element* element /*= NULL*/)
-{
-    if(element) {
-        DOMWarning(message,element->KeyToken());
-        return;
-    }
-    if(DefaultLogger::get()) {
-        ASSIMP_LOG_WARN("FBX-DOM: " + message);
-    }
-}
-
-
-// ------------------------------------------------------------------------------------------------
-// fetch a property table and the corresponding property template
-std::shared_ptr<const PropertyTable> GetPropertyTable(const Document& doc,
-    const std::string& templateName,
-    const Element &element,
-    const Scope& sc,
-    bool no_warn /*= false*/)
-{
-    const Element* const Properties70 = sc["Properties70"];
-    std::shared_ptr<const PropertyTable> templateProps = std::shared_ptr<const PropertyTable>(
-        static_cast<const PropertyTable*>(NULL));
-
-    if(templateName.length()) {
-        PropertyTemplateMap::const_iterator it = doc.Templates().find(templateName);
-        if(it != doc.Templates().end()) {
-            templateProps = (*it).second;
-        }
-    }
-
-    if(!Properties70 || !Properties70->Compound()) {
-        if(!no_warn) {
-            DOMWarning("property table (Properties70) not found",&element);
-        }
-        if(templateProps) {
-            return templateProps;
-        }
-        else {
-            return std::make_shared<const PropertyTable>();
-        }
-    }
-    return std::make_shared<const PropertyTable>(*Properties70,templateProps);
-}
-} // !Util
-} // !FBX
-} // !Assimp
-
-#endif

+ 0 - 120
thirdparty/assimp/code/FBX/FBXDocumentUtil.h

@@ -1,120 +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.
-
-----------------------------------------------------------------------
-*/
-
-/** @file  FBXDocumentUtil.h
- *  @brief FBX internal utilities used by the DOM reading code
- */
-#ifndef INCLUDED_AI_FBX_DOCUMENT_UTIL_H
-#define INCLUDED_AI_FBX_DOCUMENT_UTIL_H
-
-#include <assimp/defs.h>
-#include <string>
-#include <memory>
-#include "FBXDocument.h"
-
-struct Token;
-struct Element;
-
-namespace Assimp {
-namespace FBX {
-namespace Util {
-
-/* DOM/Parse error reporting - does not return */
-AI_WONT_RETURN void DOMError(const std::string& message, const Token& token) AI_WONT_RETURN_SUFFIX;
-AI_WONT_RETURN void DOMError(const std::string& message, const Element* element = NULL) AI_WONT_RETURN_SUFFIX;
-
-// does return
-void DOMWarning(const std::string& message, const Token& token);
-void DOMWarning(const std::string& message, const Element* element = NULL);
-
-
-// fetch a property table and the corresponding property template
-std::shared_ptr<const PropertyTable> GetPropertyTable(const Document& doc,
-    const std::string& templateName,
-    const Element &element,
-    const Scope& sc,
-    bool no_warn = false);
-
-// ------------------------------------------------------------------------------------------------
-template <typename T>
-inline
-const T* ProcessSimpleConnection(const Connection& con,
-    bool is_object_property_conn,
-    const char* name,
-    const Element& element,
-    const char** propNameOut = nullptr)
-{
-    if (is_object_property_conn && !con.PropertyName().length()) {
-        DOMWarning("expected incoming " + std::string(name) +
-            " link to be an object-object connection, ignoring",
-            &element
-            );
-        return nullptr;
-    }
-    else if (!is_object_property_conn && con.PropertyName().length()) {
-        DOMWarning("expected incoming " + std::string(name) +
-            " link to be an object-property connection, ignoring",
-            &element
-            );
-        return nullptr;
-    }
-
-    if(is_object_property_conn && propNameOut) {
-        // note: this is ok, the return value of PropertyValue() is guaranteed to
-        // remain valid and unchanged as long as the document exists.
-        *propNameOut = con.PropertyName().c_str();
-    }
-
-    const Object* const ob = con.SourceObject();
-    if(!ob) {
-        DOMWarning("failed to read source object for incoming " + std::string(name) +
-            " link, ignoring",
-            &element);
-        return nullptr;
-    }
-
-    return dynamic_cast<const T*>(ob);
-}
-
-} //!Util
-} //!FBX
-} //!Assimp
-
-#endif

+ 0 - 571
thirdparty/assimp/code/FBX/FBXExportNode.cpp

@@ -1,571 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, 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_EXPORT
-#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
-
-#include "FBXExportNode.h"
-#include "FBXCommon.h"
-
-#include <assimp/StreamWriter.h> // StreamWriterLE
-#include <assimp/Exceptional.h> // DeadlyExportError
-#include <assimp/ai_assert.h>
-#include <assimp/StringUtils.h> // ai_snprintf
-
-#include <string>
-#include <ostream>
-#include <sstream> // ostringstream
-#include <memory> // shared_ptr
-
-namespace Assimp {
-// AddP70<type> helpers... there's no usable pattern here,
-// so all are defined as separate functions.
-// Even "animatable" properties are often completely different
-// from the standard (nonanimated) property definition,
-// so they are specified with an 'A' suffix.
-
-void FBX::Node::AddP70int(
-    const std::string& name, int32_t value
-) {
-    FBX::Node n("P");
-    n.AddProperties(name, "int", "Integer", "", value);
-    AddChild(n);
-}
-
-void FBX::Node::AddP70bool(
-    const std::string& name, bool value
-) {
-    FBX::Node n("P");
-    n.AddProperties(name, "bool", "", "", int32_t(value));
-    AddChild(n);
-}
-
-void FBX::Node::AddP70double(
-    const std::string& name, double value
-) {
-    FBX::Node n("P");
-    n.AddProperties(name, "double", "Number", "", value);
-    AddChild(n);
-}
-
-void FBX::Node::AddP70numberA(
-    const std::string& name, double value
-) {
-    FBX::Node n("P");
-    n.AddProperties(name, "Number", "", "A", value);
-    AddChild(n);
-}
-
-void FBX::Node::AddP70color(
-    const std::string& name, double r, double g, double b
-) {
-    FBX::Node n("P");
-    n.AddProperties(name, "ColorRGB", "Color", "", r, g, b);
-    AddChild(n);
-}
-
-void FBX::Node::AddP70colorA(
-    const std::string& name, double r, double g, double b
-) {
-    FBX::Node n("P");
-    n.AddProperties(name, "Color", "", "A", r, g, b);
-    AddChild(n);
-}
-
-void FBX::Node::AddP70vector(
-    const std::string& name, double x, double y, double z
-) {
-    FBX::Node n("P");
-    n.AddProperties(name, "Vector3D", "Vector", "", x, y, z);
-    AddChild(n);
-}
-
-void FBX::Node::AddP70vectorA(
-    const std::string& name, double x, double y, double z
-) {
-    FBX::Node n("P");
-    n.AddProperties(name, "Vector", "", "A", x, y, z);
-    AddChild(n);
-}
-
-void FBX::Node::AddP70string(
-    const std::string& name, const std::string& value
-) {
-    FBX::Node n("P");
-    n.AddProperties(name, "KString", "", "", value);
-    AddChild(n);
-}
-
-void FBX::Node::AddP70enum(
-    const std::string& name, int32_t value
-) {
-    FBX::Node n("P");
-    n.AddProperties(name, "enum", "", "", value);
-    AddChild(n);
-}
-
-void FBX::Node::AddP70time(
-    const std::string& name, int64_t value
-) {
-    FBX::Node n("P");
-    n.AddProperties(name, "KTime", "Time", "", value);
-    AddChild(n);
-}
-
-
-// public member functions for writing nodes to stream
-
-void FBX::Node::Dump(
-    std::shared_ptr<Assimp::IOStream> outfile,
-    bool binary, int indent
-) {
-    if (binary) {
-        Assimp::StreamWriterLE outstream(outfile);
-        DumpBinary(outstream);
-    } else {
-        std::ostringstream ss;
-        DumpAscii(ss, indent);
-        std::string s = ss.str();
-        outfile->Write(s.c_str(), s.size(), 1);
-    }
-}
-
-void FBX::Node::Dump(
-    Assimp::StreamWriterLE &outstream,
-    bool binary, int indent
-) {
-    if (binary) {
-        DumpBinary(outstream);
-    } else {
-        std::ostringstream ss;
-        DumpAscii(ss, indent);
-        outstream.PutString(ss.str());
-    }
-}
-
-
-// public member functions for low-level writing
-
-void FBX::Node::Begin(
-    Assimp::StreamWriterLE &s,
-    bool binary, int indent
-) {
-    if (binary) {
-        BeginBinary(s);
-    } else {
-        // assume we're at the correct place to start already
-        (void)indent;
-        std::ostringstream ss;
-        BeginAscii(ss, indent);
-        s.PutString(ss.str());
-    }
-}
-
-void FBX::Node::DumpProperties(
-    Assimp::StreamWriterLE& s,
-    bool binary, int indent
-) {
-    if (binary) {
-        DumpPropertiesBinary(s);
-    } else {
-        std::ostringstream ss;
-        DumpPropertiesAscii(ss, indent);
-        s.PutString(ss.str());
-    }
-}
-
-void FBX::Node::EndProperties(
-    Assimp::StreamWriterLE &s,
-    bool binary, int indent
-) {
-    EndProperties(s, binary, indent, properties.size());
-}
-
-void FBX::Node::EndProperties(
-    Assimp::StreamWriterLE &s,
-    bool binary, int indent,
-    size_t num_properties
-) {
-    if (binary) {
-        EndPropertiesBinary(s, num_properties);
-    } else {
-        // nothing to do
-        (void)indent;
-    }
-}
-
-void FBX::Node::BeginChildren(
-    Assimp::StreamWriterLE &s,
-    bool binary, int indent
-) {
-    if (binary) {
-        // nothing to do
-    } else {
-        std::ostringstream ss;
-        BeginChildrenAscii(ss, indent);
-        s.PutString(ss.str());
-    }
-}
-
-void FBX::Node::DumpChildren(
-    Assimp::StreamWriterLE& s,
-    bool binary, int indent
-) {
-    if (binary) {
-        DumpChildrenBinary(s);
-    } else {
-        std::ostringstream ss;
-        DumpChildrenAscii(ss, indent);
-        if (ss.tellp() > 0)
-            s.PutString(ss.str());
-    }
-}
-
-void FBX::Node::End(
-    Assimp::StreamWriterLE &s,
-    bool binary, int indent,
-    bool has_children
-) {
-    if (binary) {
-        EndBinary(s, has_children);
-    } else {
-        std::ostringstream ss;
-        EndAscii(ss, indent, has_children);
-        if (ss.tellp() > 0)
-            s.PutString(ss.str());
-    }
-}
-
-
-// public member functions for writing to binary fbx
-
-void FBX::Node::DumpBinary(Assimp::StreamWriterLE &s)
-{
-    // write header section (with placeholders for some things)
-    BeginBinary(s);
-
-    // write properties
-    DumpPropertiesBinary(s);
-
-    // go back and fill in property related placeholders
-    EndPropertiesBinary(s, properties.size());
-
-    // write children
-    DumpChildrenBinary(s);
-
-    // finish, filling in end offset placeholder
-    EndBinary(s, force_has_children || !children.empty());
-}
-
-
-// public member functions for writing to ascii fbx
-
-void FBX::Node::DumpAscii(std::ostream &s, int indent)
-{
-    // write name
-    BeginAscii(s, indent);
-
-    // write properties
-    DumpPropertiesAscii(s, indent);
-
-    if (force_has_children || !children.empty()) {
-        // begin children (with a '{')
-        BeginChildrenAscii(s, indent + 1);
-        // write children
-        DumpChildrenAscii(s, indent + 1);
-    }
-
-    // finish (also closing the children bracket '}')
-    EndAscii(s, indent, force_has_children || !children.empty());
-}
-
-
-// private member functions for low-level writing to fbx
-
-void FBX::Node::BeginBinary(Assimp::StreamWriterLE &s)
-{
-    // remember start pos so we can come back and write the end pos
-    this->start_pos = s.Tell();
-
-    // placeholders for end pos and property section info
-    s.PutU4(0); // end pos
-    s.PutU4(0); // number of properties
-    s.PutU4(0); // total property section length
-
-    // node name
-    s.PutU1(uint8_t(name.size())); // length of node name
-    s.PutString(name); // node name as raw bytes
-
-    // property data comes after here
-    this->property_start = s.Tell();
-}
-
-void FBX::Node::DumpPropertiesBinary(Assimp::StreamWriterLE& s)
-{
-    for (auto &p : properties) {
-        p.DumpBinary(s);
-    }
-}
-
-void FBX::Node::EndPropertiesBinary(
-    Assimp::StreamWriterLE &s,
-    size_t num_properties
-) {
-    if (num_properties == 0) { return; }
-    size_t pos = s.Tell();
-    ai_assert(pos > property_start);
-    size_t property_section_size = pos - property_start;
-    s.Seek(start_pos + 4);
-    s.PutU4(uint32_t(num_properties));
-    s.PutU4(uint32_t(property_section_size));
-    s.Seek(pos);
-}
-
-void FBX::Node::DumpChildrenBinary(Assimp::StreamWriterLE& s)
-{
-    for (FBX::Node& child : children) {
-        child.DumpBinary(s);
-    }
-}
-
-void FBX::Node::EndBinary(
-    Assimp::StreamWriterLE &s,
-    bool has_children
-) {
-    // if there were children, add a null record
-    if (has_children) { s.PutString(Assimp::FBX::NULL_RECORD); }
-
-    // now go back and write initial pos
-    this->end_pos = s.Tell();
-    s.Seek(start_pos);
-    s.PutU4(uint32_t(end_pos));
-    s.Seek(end_pos);
-}
-
-
-void FBX::Node::BeginAscii(std::ostream& s, int indent)
-{
-    s << '\n';
-    for (int i = 0; i < indent; ++i) { s << '\t'; }
-    s << name << ": ";
-}
-
-void FBX::Node::DumpPropertiesAscii(std::ostream &s, int indent)
-{
-    for (size_t i = 0; i < properties.size(); ++i) {
-        if (i > 0) { s << ", "; }
-        properties[i].DumpAscii(s, indent);
-    }
-}
-
-void FBX::Node::BeginChildrenAscii(std::ostream& s, int indent)
-{
-    // only call this if there are actually children
-    s << " {";
-    (void)indent;
-}
-
-void FBX::Node::DumpChildrenAscii(std::ostream& s, int indent)
-{
-    // children will need a lot of padding and corralling
-    if (children.size() || force_has_children) {
-        for (size_t i = 0; i < children.size(); ++i) {
-            // no compression in ascii files, so skip this node if it exists
-            if (children[i].name == "EncryptionType") { continue; }
-            // the child can dump itself
-            children[i].DumpAscii(s, indent);
-        }
-    }
-}
-
-void FBX::Node::EndAscii(std::ostream& s, int indent, bool has_children)
-{
-    if (!has_children) { return; } // nothing to do
-    s << '\n';
-    for (int i = 0; i < indent; ++i) { s << '\t'; }
-    s << "}";
-}
-
-// private helpers for static member functions
-
-// ascii property node from vector of doubles
-void FBX::Node::WritePropertyNodeAscii(
-    const std::string& name,
-    const std::vector<double>& v,
-    Assimp::StreamWriterLE& s,
-    int indent
-){
-    char buffer[32];
-    FBX::Node node(name);
-    node.Begin(s, false, indent);
-    std::string vsize = to_string(v.size());
-    // *<size> {
-    s.PutChar('*'); s.PutString(vsize); s.PutString(" {\n");
-    // indent + 1
-    for (int i = 0; i < indent + 1; ++i) { s.PutChar('\t'); }
-    // a: value,value,value,...
-    s.PutString("a: ");
-    int count = 0;
-    for (size_t i = 0; i < v.size(); ++i) {
-        if (i > 0) { s.PutChar(','); }
-        int len = ai_snprintf(buffer, sizeof(buffer), "%f", v[i]);
-        count += len;
-        if (count > 2048) { s.PutChar('\n'); count = 0; }
-        if (len < 0 || len > 31) {
-            // this should never happen
-            throw DeadlyExportError("failed to convert double to string");
-        }
-        for (int j = 0; j < len; ++j) { s.PutChar(buffer[j]); }
-    }
-    // }
-    s.PutChar('\n');
-    for (int i = 0; i < indent; ++i) { s.PutChar('\t'); }
-    s.PutChar('}'); s.PutChar(' ');
-    node.End(s, false, indent, false);
-}
-
-// ascii property node from vector of int32_t
-void FBX::Node::WritePropertyNodeAscii(
-    const std::string& name,
-    const std::vector<int32_t>& v,
-    Assimp::StreamWriterLE& s,
-    int indent
-){
-    char buffer[32];
-    FBX::Node node(name);
-    node.Begin(s, false, indent);
-    std::string vsize = to_string(v.size());
-    // *<size> {
-    s.PutChar('*'); s.PutString(vsize); s.PutString(" {\n");
-    // indent + 1
-    for (int i = 0; i < indent + 1; ++i) { s.PutChar('\t'); }
-    // a: value,value,value,...
-    s.PutString("a: ");
-    int count = 0;
-    for (size_t i = 0; i < v.size(); ++i) {
-        if (i > 0) { s.PutChar(','); }
-        int len = ai_snprintf(buffer, sizeof(buffer), "%d", v[i]);
-        count += len;
-        if (count > 2048) { s.PutChar('\n'); count = 0; }
-        if (len < 0 || len > 31) {
-            // this should never happen
-            throw DeadlyExportError("failed to convert double to string");
-        }
-        for (int j = 0; j < len; ++j) { s.PutChar(buffer[j]); }
-    }
-    // }
-    s.PutChar('\n');
-    for (int i = 0; i < indent; ++i) { s.PutChar('\t'); }
-    s.PutChar('}'); s.PutChar(' ');
-    node.End(s, false, indent, false);
-}
-
-// binary property node from vector of doubles
-// TODO: optional zip compression!
-void FBX::Node::WritePropertyNodeBinary(
-    const std::string& name,
-    const std::vector<double>& v,
-    Assimp::StreamWriterLE& s
-){
-    FBX::Node node(name);
-    node.BeginBinary(s);
-    s.PutU1('d');
-    s.PutU4(uint32_t(v.size())); // number of elements
-    s.PutU4(0); // no encoding (1 would be zip-compressed)
-    s.PutU4(uint32_t(v.size()) * 8); // data size
-    for (auto it = v.begin(); it != v.end(); ++it) { s.PutF8(*it); }
-    node.EndPropertiesBinary(s, 1);
-    node.EndBinary(s, false);
-}
-
-// binary property node from vector of int32_t
-// TODO: optional zip compression!
-void FBX::Node::WritePropertyNodeBinary(
-    const std::string& name,
-    const std::vector<int32_t>& v,
-    Assimp::StreamWriterLE& s
-){
-    FBX::Node node(name);
-    node.BeginBinary(s);
-    s.PutU1('i');
-    s.PutU4(uint32_t(v.size())); // number of elements
-    s.PutU4(0); // no encoding (1 would be zip-compressed)
-    s.PutU4(uint32_t(v.size()) * 4); // data size
-    for (auto it = v.begin(); it != v.end(); ++it) { s.PutI4(*it); }
-    node.EndPropertiesBinary(s, 1);
-    node.EndBinary(s, false);
-}
-
-// public static member functions
-
-// convenience function to create and write a property node,
-// holding a single property which is an array of values.
-// does not copy the data, so is efficient for large arrays.
-void FBX::Node::WritePropertyNode(
-    const std::string& name,
-    const std::vector<double>& v,
-    Assimp::StreamWriterLE& s,
-    bool binary, int indent
-){
-    if (binary) {
-        FBX::Node::WritePropertyNodeBinary(name, v, s);
-    } else {
-        FBX::Node::WritePropertyNodeAscii(name, v, s, indent);
-    }
-}
-
-// convenience function to create and write a property node,
-// holding a single property which is an array of values.
-// does not copy the data, so is efficient for large arrays.
-void FBX::Node::WritePropertyNode(
-    const std::string& name,
-    const std::vector<int32_t>& v,
-    Assimp::StreamWriterLE& s,
-    bool binary, int indent
-){
-    if (binary) {
-        FBX::Node::WritePropertyNodeBinary(name, v, s);
-    } else {
-        FBX::Node::WritePropertyNodeAscii(name, v, s, indent);
-    }
-}
-}
-#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
-#endif // ASSIMP_BUILD_NO_EXPORT

+ 0 - 271
thirdparty/assimp/code/FBX/FBXExportNode.h

@@ -1,271 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-copyright notice, this list of conditions and the
-following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the
-following disclaimer in the documentation and/or other
-materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-contributors may be used to endorse or promote products
-derived from this software without specific prior
-written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file FBXExportNode.h
-* Declares the FBX::Node helper class for fbx export.
-*/
-#ifndef AI_FBXEXPORTNODE_H_INC
-#define AI_FBXEXPORTNODE_H_INC
-
-#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
-
-#include "FBXExportProperty.h"
-
-#include <assimp/StreamWriter.h> // StreamWriterLE
-
-#include <string>
-#include <vector>
-
-namespace Assimp {
-namespace FBX {
-    class Node;
-}
-
-class FBX::Node {
-public: 
-    // TODO: accessors
-    std::string name; // node name
-    std::vector<FBX::FBXExportProperty> properties; // node properties
-    std::vector<FBX::Node> children; // child nodes
-
-    // some nodes always pretend they have children...
-    bool force_has_children = false;
-
-public: // constructors
-    /// The default class constructor.
-    Node() = default;
-
-    /// The class constructor with the name.
-    Node(const std::string& n)
-    : name(n)
-    , properties()
-    , children()
-    , force_has_children( false ) {
-        // empty
-    }
-
-    // convenience template to construct with properties directly
-    template <typename... More>
-    Node(const std::string& n, const More... more)
-    : name(n)
-    , properties()
-    , children()
-    , force_has_children(false) {
-        AddProperties(more...);
-    }
-
-public: // functions to add properties or children
-    // add a single property to the node
-    template <typename T>
-    void AddProperty(T value) {
-        properties.emplace_back(value);
-    }
-
-    // convenience function to add multiple properties at once
-    template <typename T, typename... More>
-    void AddProperties(T value, More... more) {
-        properties.emplace_back(value);
-        AddProperties(more...);
-    }
-    void AddProperties() {}
-
-    // add a child node directly
-    void AddChild(const Node& node) { children.push_back(node); }
-
-    // convenience function to add a child node with a single property
-    template <typename... More>
-    void AddChild(
-        const std::string& name,
-        More... more
-    ) {
-        FBX::Node c(name);
-        c.AddProperties(more...);
-        children.push_back(c);
-    }
-
-public: // support specifically for dealing with Properties70 nodes
-
-    // it really is simpler to make these all separate functions.
-    // the versions with 'A' suffixes are for animatable properties.
-    // those often follow a completely different format internally in FBX.
-    void AddP70int(const std::string& name, int32_t value);
-    void AddP70bool(const std::string& name, bool value);
-    void AddP70double(const std::string& name, double value);
-    void AddP70numberA(const std::string& name, double value);
-    void AddP70color(const std::string& name, double r, double g, double b);
-    void AddP70colorA(const std::string& name, double r, double g, double b);
-    void AddP70vector(const std::string& name, double x, double y, double z);
-    void AddP70vectorA(const std::string& name, double x, double y, double z);
-    void AddP70string(const std::string& name, const std::string& value);
-    void AddP70enum(const std::string& name, int32_t value);
-    void AddP70time(const std::string& name, int64_t value);
-
-    // template for custom P70 nodes.
-    // anything that doesn't fit in the above can be created manually.
-    template <typename... More>
-    void AddP70(
-        const std::string& name,
-        const std::string& type,
-        const std::string& type2,
-        const std::string& flags,
-        More... more
-    ) {
-        Node n("P");
-        n.AddProperties(name, type, type2, flags, more...);
-        AddChild(n);
-    }
-
-public: // member functions for writing data to a file or stream
-
-    // write the full node to the given file or stream
-    void Dump(
-        std::shared_ptr<Assimp::IOStream> outfile,
-        bool binary, int indent
-    );
-    void Dump(Assimp::StreamWriterLE &s, bool binary, int indent);
-
-    // these other functions are for writing data piece by piece.
-    // they must be used carefully.
-    // for usage examples see FBXExporter.cpp.
-    void Begin(Assimp::StreamWriterLE &s, bool binary, int indent);
-    void DumpProperties(Assimp::StreamWriterLE& s, bool binary, int indent);
-    void EndProperties(Assimp::StreamWriterLE &s, bool binary, int indent);
-    void EndProperties(
-        Assimp::StreamWriterLE &s, bool binary, int indent,
-        size_t num_properties
-    );
-    void BeginChildren(Assimp::StreamWriterLE &s, bool binary, int indent);
-    void DumpChildren(Assimp::StreamWriterLE& s, bool binary, int indent);
-    void End(
-        Assimp::StreamWriterLE &s, bool binary, int indent,
-        bool has_children
-    );
-
-private: // internal functions used for writing
-
-    void DumpBinary(Assimp::StreamWriterLE &s);
-    void DumpAscii(Assimp::StreamWriterLE &s, int indent);
-    void DumpAscii(std::ostream &s, int indent);
-
-    void BeginBinary(Assimp::StreamWriterLE &s);
-    void DumpPropertiesBinary(Assimp::StreamWriterLE& s);
-    void EndPropertiesBinary(Assimp::StreamWriterLE &s);
-    void EndPropertiesBinary(Assimp::StreamWriterLE &s, size_t num_properties);
-    void DumpChildrenBinary(Assimp::StreamWriterLE& s);
-    void EndBinary(Assimp::StreamWriterLE &s, bool has_children);
-
-    void BeginAscii(std::ostream &s, int indent);
-    void DumpPropertiesAscii(std::ostream &s, int indent);
-    void BeginChildrenAscii(std::ostream &s, int indent);
-    void DumpChildrenAscii(std::ostream &s, int indent);
-    void EndAscii(std::ostream &s, int indent, bool has_children);
-
-private: // data used for binary dumps
-    size_t start_pos; // starting position in stream
-    size_t end_pos; // ending position in stream
-    size_t property_start; // starting position of property section
-
-public: // static member functions
-
-    // convenience function to create a node with a single property,
-    // and write it to the stream.
-    template <typename T>
-    static void WritePropertyNode(
-        const std::string& name,
-        const T value,
-        Assimp::StreamWriterLE& s,
-        bool binary, int indent
-    ) {
-        FBX::FBXExportProperty p(value);
-        FBX::Node node(name, p);
-        node.Dump(s, binary, indent);
-    }
-
-    // convenience function to create and write a property node,
-    // holding a single property which is an array of values.
-    // does not copy the data, so is efficient for large arrays.
-    static void WritePropertyNode(
-        const std::string& name,
-        const std::vector<double>& v,
-        Assimp::StreamWriterLE& s,
-        bool binary, int indent
-    );
-
-    // convenience function to create and write a property node,
-    // holding a single property which is an array of values.
-    // does not copy the data, so is efficient for large arrays.
-    static void WritePropertyNode(
-        const std::string& name,
-        const std::vector<int32_t>& v,
-        Assimp::StreamWriterLE& s,
-        bool binary, int indent
-    );
-
-private: // static helper functions
-    static void WritePropertyNodeAscii(
-        const std::string& name,
-        const std::vector<double>& v,
-        Assimp::StreamWriterLE& s,
-        int indent
-    );
-    static void WritePropertyNodeAscii(
-        const std::string& name,
-        const std::vector<int32_t>& v,
-        Assimp::StreamWriterLE& s,
-        int indent
-    );
-    static void WritePropertyNodeBinary(
-        const std::string& name,
-        const std::vector<double>& v,
-        Assimp::StreamWriterLE& s
-    );
-    static void WritePropertyNodeBinary(
-        const std::string& name,
-        const std::vector<int32_t>& v,
-        Assimp::StreamWriterLE& s
-    );
-
-};
-}
-
-#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
-
-#endif // AI_FBXEXPORTNODE_H_INC

+ 0 - 385
thirdparty/assimp/code/FBX/FBXExportProperty.cpp

@@ -1,385 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, 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_EXPORT
-#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
-
-#include "FBXExportProperty.h"
-
-#include <assimp/StreamWriter.h> // StreamWriterLE
-#include <assimp/Exceptional.h> // DeadlyExportError
-
-#include <string>
-#include <vector>
-#include <ostream>
-#include <locale>
-#include <sstream> // ostringstream
-
-namespace Assimp {
-namespace FBX {
-
-// constructors for single element properties
-
-FBXExportProperty::FBXExportProperty(bool v)
-: type('C')
-, data(1, uint8_t(v)) {}
-
-FBXExportProperty::FBXExportProperty(int16_t v)
-: type('Y')
-, data(2) {
-    uint8_t* d = data.data();
-    (reinterpret_cast<int16_t*>(d))[0] = v;
-}
-
-FBXExportProperty::FBXExportProperty(int32_t v)
-: type('I')
-, data(4) {
-    uint8_t* d = data.data();
-    (reinterpret_cast<int32_t*>(d))[0] = v;
-}
-
-FBXExportProperty::FBXExportProperty(float v)
-: type('F')
-, data(4) {
-    uint8_t* d = data.data();
-    (reinterpret_cast<float*>(d))[0] = v;
-}
-
-FBXExportProperty::FBXExportProperty(double v)
-: type('D')
-, data(8) {
-    uint8_t* d = data.data();
-    (reinterpret_cast<double*>(d))[0] = v;
-}
-
-FBXExportProperty::FBXExportProperty(int64_t v)
-: type('L')
-, data(8) {
-    uint8_t* d = data.data();
-    (reinterpret_cast<int64_t*>(d))[0] = v;
-}
-
-// constructors for array-type properties
-
-FBXExportProperty::FBXExportProperty(const char* c, bool raw)
-: FBXExportProperty(std::string(c), raw) {
-    // empty
-}
-
-// strings can either be saved as "raw" (R) data, or "string" (S) data
-FBXExportProperty::FBXExportProperty(const std::string& s, bool raw)
-: type(raw ? 'R' : 'S')
-, data(s.size()) {
-    for (size_t i = 0; i < s.size(); ++i) {
-        data[i] = uint8_t(s[i]);
-    }
-}
-
-FBXExportProperty::FBXExportProperty(const std::vector<uint8_t>& r)
-: type('R')
-, data(r) {
-    // empty
-}
-
-FBXExportProperty::FBXExportProperty(const std::vector<int32_t>& va)
-: type('i')
-, data(4 * va.size() ) {
-    int32_t* d = reinterpret_cast<int32_t*>(data.data());
-    for (size_t i = 0; i < va.size(); ++i) {
-        d[i] = va[i];
-    }
-}
-
-FBXExportProperty::FBXExportProperty(const std::vector<int64_t>& va)
-: type('l')
-, data(8 * va.size()) {
-    int64_t* d = reinterpret_cast<int64_t*>(data.data());
-    for (size_t i = 0; i < va.size(); ++i) {
-        d[i] = va[i];
-    }
-}
-
-FBXExportProperty::FBXExportProperty(const std::vector<float>& va)
-: type('f')
-, data(4 * va.size()) {
-    float* d = reinterpret_cast<float*>(data.data());
-    for (size_t i = 0; i < va.size(); ++i) {
-        d[i] = va[i];
-    }
-}
-
-FBXExportProperty::FBXExportProperty(const std::vector<double>& va)
-: type('d')
-, data(8 * va.size()) {
-    double* d = reinterpret_cast<double*>(data.data());
-    for (size_t i = 0; i < va.size(); ++i) {
-        d[i] = va[i];
-    }
-}
-
-FBXExportProperty::FBXExportProperty(const aiMatrix4x4& vm)
-: type('d')
-, data(8 * 16) {
-    double* d = reinterpret_cast<double*>(data.data());
-    for (unsigned int c = 0; c < 4; ++c) {
-        for (unsigned int r = 0; r < 4; ++r) {
-            d[4 * c + r] = vm[r][c];
-        }
-    }
-}
-
-// public member functions
-
-size_t FBXExportProperty::size() {
-    switch (type) {
-        case 'C':
-        case 'Y':
-        case 'I':
-        case 'F':
-        case 'D':
-        case 'L':
-            return data.size() + 1;
-        case 'S':
-        case 'R':
-            return data.size() + 5;
-        case 'i':
-        case 'd':
-            return data.size() + 13;
-        default:
-            throw DeadlyExportError("Requested size on property of unknown type");
-    }
-}
-
-void FBXExportProperty::DumpBinary(Assimp::StreamWriterLE& s) {
-    s.PutU1(type);
-    uint8_t* d = data.data();
-    size_t N;
-    switch (type) {
-        case 'C': s.PutU1(*(reinterpret_cast<uint8_t*>(d))); return;
-        case 'Y': s.PutI2(*(reinterpret_cast<int16_t*>(d))); return;
-        case 'I': s.PutI4(*(reinterpret_cast<int32_t*>(d))); return;
-        case 'F': s.PutF4(*(reinterpret_cast<float*>(d))); return;
-        case 'D': s.PutF8(*(reinterpret_cast<double*>(d))); return;
-        case 'L': s.PutI8(*(reinterpret_cast<int64_t*>(d))); return;
-        case 'S':
-        case 'R':
-            s.PutU4(uint32_t(data.size()));
-            for (size_t i = 0; i < data.size(); ++i) { s.PutU1(data[i]); }
-            return;
-        case 'i':
-            N = data.size() / 4;
-            s.PutU4(uint32_t(N)); // number of elements
-            s.PutU4(0); // no encoding (1 would be zip-compressed)
-            // TODO: compress if large?
-            s.PutU4(uint32_t(data.size())); // data size
-            for (size_t i = 0; i < N; ++i) {
-                s.PutI4((reinterpret_cast<int32_t*>(d))[i]);
-            }
-            return;
-        case 'l':
-            N = data.size() / 8;
-            s.PutU4(uint32_t(N)); // number of elements
-            s.PutU4(0); // no encoding (1 would be zip-compressed)
-            // TODO: compress if large?
-            s.PutU4(uint32_t(data.size())); // data size
-            for (size_t i = 0; i < N; ++i) {
-                s.PutI8((reinterpret_cast<int64_t*>(d))[i]);
-            }
-            return;
-        case 'f':
-            N = data.size() / 4;
-            s.PutU4(uint32_t(N)); // number of elements
-            s.PutU4(0); // no encoding (1 would be zip-compressed)
-            // TODO: compress if large?
-            s.PutU4(uint32_t(data.size())); // data size
-            for (size_t i = 0; i < N; ++i) {
-                s.PutF4((reinterpret_cast<float*>(d))[i]);
-            }
-            return;
-        case 'd':
-            N = data.size() / 8;
-            s.PutU4(uint32_t(N)); // number of elements
-            s.PutU4(0); // no encoding (1 would be zip-compressed)
-            // TODO: compress if large?
-            s.PutU4(uint32_t(data.size())); // data size
-            for (size_t i = 0; i < N; ++i) {
-                s.PutF8((reinterpret_cast<double*>(d))[i]);
-            }
-            return;
-        default:
-            std::ostringstream err;
-            err << "Tried to dump property with invalid type '";
-            err << type << "'!";
-            throw DeadlyExportError(err.str());
-    }
-}
-
-void FBXExportProperty::DumpAscii(Assimp::StreamWriterLE& outstream, int indent) {
-    std::ostringstream ss;
-    ss.imbue(std::locale::classic());
-    ss.precision(15); // this seems to match official FBX SDK exports
-    DumpAscii(ss, indent);
-    outstream.PutString(ss.str());
-}
-
-void FBXExportProperty::DumpAscii(std::ostream& s, int indent) {
-    // no writing type... or anything. just shove it into the stream.
-    uint8_t* d = data.data();
-    size_t N;
-    size_t swap = data.size();
-    size_t count = 0;
-    switch (type) {
-    case 'C':
-        if (*(reinterpret_cast<uint8_t*>(d))) { s << 'T'; }
-        else { s << 'F'; }
-        return;
-    case 'Y': s << *(reinterpret_cast<int16_t*>(d)); return;
-    case 'I': s << *(reinterpret_cast<int32_t*>(d)); return;
-    case 'F': s << *(reinterpret_cast<float*>(d)); return;
-    case 'D': s << *(reinterpret_cast<double*>(d)); return;
-    case 'L': s << *(reinterpret_cast<int64_t*>(d)); return;
-    case 'S':
-        // first search to see if it has "\x00\x01" in it -
-        // which separates fields which are reversed in the ascii version.
-        // yeah.
-        // FBX, yeah.
-        for (size_t i = 0; i < data.size(); ++i) {
-            if (data[i] == '\0') {
-                swap = i;
-                break;
-            }
-        }
-    case 'R':
-        s << '"';
-        // we might as well check this now,
-        // probably it will never happen
-        for (size_t i = 0; i < data.size(); ++i) {
-            char c = data[i];
-            if (c == '"') {
-                throw runtime_error("can't handle quotes in property string");
-            }
-        }
-        // first write the SWAPPED member (if any)
-        for (size_t i = swap + 2; i < data.size(); ++i) {
-            char c = data[i];
-            s << c;
-        }
-        // then a separator
-        if (swap != data.size()) {
-            s << "::";
-        }
-        // then the initial member
-        for (size_t i = 0; i < swap; ++i) {
-            char c = data[i];
-            s << c;
-        }
-        s << '"';
-        return;
-    case 'i':
-        N = data.size() / 4; // number of elements
-        s << '*' << N << " {\n";
-        for (int i = 0; i < indent + 1; ++i) { s << '\t'; }
-        s << "a: ";
-        for (size_t i = 0; i < N; ++i) {
-            if (i > 0) { s << ','; }
-            if (count++ > 120) { s << '\n'; count = 0; }
-            s << (reinterpret_cast<int32_t*>(d))[i];
-        }
-        s << '\n';
-        for (int i = 0; i < indent; ++i) { s << '\t'; }
-        s << "} ";
-        return;
-    case 'l':
-        N = data.size() / 8;
-        s << '*' << N << " {\n";
-        for (int i = 0; i < indent + 1; ++i) { s << '\t'; }
-        s << "a: ";
-        for (size_t i = 0; i < N; ++i) {
-            if (i > 0) { s << ','; }
-            if (count++ > 120) { s << '\n'; count = 0; }
-            s << (reinterpret_cast<int64_t*>(d))[i];
-        }
-        s << '\n';
-        for (int i = 0; i < indent; ++i) { s << '\t'; }
-        s << "} ";
-        return;
-    case 'f':
-        N = data.size() / 4;
-        s << '*' << N << " {\n";
-        for (int i = 0; i < indent + 1; ++i) { s << '\t'; }
-        s << "a: ";
-        for (size_t i = 0; i < N; ++i) {
-            if (i > 0) { s << ','; }
-            if (count++ > 120) { s << '\n'; count = 0; }
-            s << (reinterpret_cast<float*>(d))[i];
-        }
-        s << '\n';
-        for (int i = 0; i < indent; ++i) { s << '\t'; }
-        s << "} ";
-        return;
-    case 'd':
-        N = data.size() / 8;
-        s << '*' << N << " {\n";
-        for (int i = 0; i < indent + 1; ++i) { s << '\t'; }
-        s << "a: ";
-        // set precision to something that can handle doubles
-        s.precision(15);
-        for (size_t i = 0; i < N; ++i) {
-            if (i > 0) { s << ','; }
-            if (count++ > 120) { s << '\n'; count = 0; }
-            s << (reinterpret_cast<double*>(d))[i];
-        }
-        s << '\n';
-        for (int i = 0; i < indent; ++i) { s << '\t'; }
-        s << "} ";
-        return;
-    default:
-        std::ostringstream err;
-        err << "Tried to dump property with invalid type '";
-        err << type << "'!";
-        throw runtime_error(err.str());
-    }
-}
-
-} // Namespace FBX
-} // Namespace Assimp
-
-#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
-#endif // ASSIMP_BUILD_NO_EXPORT

+ 0 - 129
thirdparty/assimp/code/FBX/FBXExportProperty.h

@@ -1,129 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-copyright notice, this list of conditions and the
-following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the
-following disclaimer in the documentation and/or other
-materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-contributors may be used to endorse or promote products
-derived from this software without specific prior
-written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file FBXExportProperty.h
-* Declares the FBX::Property helper class for fbx export.
-*/
-#ifndef AI_FBXEXPORTPROPERTY_H_INC
-#define AI_FBXEXPORTPROPERTY_H_INC
-
-#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
-
-#include <assimp/types.h> // aiMatrix4x4
-#include <assimp/StreamWriter.h> // StreamWriterLE
-
-#include <string>
-#include <vector>
-#include <ostream>
-#include <type_traits> // is_void
-
-namespace Assimp {
-namespace FBX {
-
-/** @brief FBX::Property
- *
- *  Holds a value of any of FBX's recognized types,
- *  each represented by a particular one-character code.
- *  C : 1-byte uint8, usually 0x00 or 0x01 to represent boolean false and true
- *  Y : 2-byte int16
- *  I : 4-byte int32
- *  F : 4-byte float
- *  D : 8-byte double
- *  L : 8-byte int64
- *  i : array of int32
- *  f : array of float
- *  d : array of double
- *  l : array of int64
- *  b : array of 1-byte booleans (0x00 or 0x01)
- *  S : string (array of 1-byte char)
- *  R : raw data (array of bytes)
- */
-class FBXExportProperty {
-public:
-    // constructors for basic types.
-    // all explicit to avoid accidental typecasting
-    explicit FBXExportProperty(bool v);
-    // TODO: determine if there is actually a byte type,
-    // or if this always means <bool>. 'C' seems to imply <char>,
-    // so possibly the above was intended to represent both.
-    explicit FBXExportProperty(int16_t v);
-    explicit FBXExportProperty(int32_t v);
-    explicit FBXExportProperty(float v);
-    explicit FBXExportProperty(double v);
-    explicit FBXExportProperty(int64_t v);
-    // strings can either be stored as 'R' (raw) or 'S' (string) type
-    explicit FBXExportProperty(const char* c, bool raw = false);
-    explicit FBXExportProperty(const std::string& s, bool raw = false);
-    explicit FBXExportProperty(const std::vector<uint8_t>& r);
-    explicit FBXExportProperty(const std::vector<int32_t>& va);
-    explicit FBXExportProperty(const std::vector<int64_t>& va);
-    explicit FBXExportProperty(const std::vector<double>& va);
-    explicit FBXExportProperty(const std::vector<float>& va);
-    explicit FBXExportProperty(const aiMatrix4x4& vm);
-
-    // this will catch any type not defined above,
-    // so that we don't accidentally convert something we don't want.
-    // for example (const char*) --> (bool)... seriously wtf C++
-    template <class T>
-    explicit FBXExportProperty(T v) : type('X') {
-        static_assert(std::is_void<T>::value, "TRIED TO CREATE FBX PROPERTY WITH UNSUPPORTED TYPE, CHECK YOUR PROPERTY INSTANTIATION");
-    } // note: no line wrap so it appears verbatim on the compiler error
-
-    // the size of this property node in a binary file, in bytes
-    size_t size();
-
-    // write this property node as binary data to the given stream
-    void DumpBinary(Assimp::StreamWriterLE& s);
-    void DumpAscii(Assimp::StreamWriterLE& s, int indent = 0);
-    void DumpAscii(std::ostream& s, int indent = 0);
-    // note: make sure the ostream is in classic "C" locale
-
-private:
-    char type;
-    std::vector<uint8_t> data;
-};
-
-} // Namespace FBX
-} // Namespace Assimp
-
-#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
-
-#endif // AI_FBXEXPORTPROPERTY_H_INC

+ 0 - 2556
thirdparty/assimp/code/FBX/FBXExporter.cpp

@@ -1,2556 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, 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_EXPORT
-#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
-
-#include "FBXExporter.h"
-#include "FBXExportNode.h"
-#include "FBXExportProperty.h"
-#include "FBXCommon.h"
-#include "FBXUtil.h"
-
-#include <assimp/version.h> // aiGetVersion
-#include <assimp/IOSystem.hpp>
-#include <assimp/Exporter.hpp>
-#include <assimp/DefaultLogger.hpp>
-#include <assimp/StreamWriter.h> // StreamWriterLE
-#include <assimp/Exceptional.h> // DeadlyExportError
-#include <assimp/material.h> // aiTextureType
-#include <assimp/scene.h>
-#include <assimp/mesh.h>
-
-// Header files, standard library.
-#include <memory> // shared_ptr
-#include <string>
-#include <sstream> // stringstream
-#include <ctime> // localtime, tm_*
-#include <map>
-#include <set>
-#include <vector>
-#include <array>
-#include <unordered_set>
-#include <numeric>
-
-// RESOURCES:
-// https://code.blender.org/2013/08/fbx-binary-file-format-specification/
-// https://wiki.blender.org/index.php/User:Mont29/Foundation/FBX_File_Structure
-
-const ai_real DEG = ai_real( 57.29577951308232087679815481 ); // degrees per radian
-
-using namespace Assimp;
-using namespace Assimp::FBX;
-
-// some constants that we'll use for writing metadata
-namespace Assimp {
-namespace FBX {
-    const std::string EXPORT_VERSION_STR = "7.4.0";
-    const uint32_t EXPORT_VERSION_INT = 7400; // 7.4 == 2014/2015
-    // FBX files have some hashed values that depend on the creation time field,
-    // but for now we don't actually know how to generate these.
-    // what we can do is set them to a known-working version.
-    // this is the data that Blender uses in their FBX export process.
-    const std::string GENERIC_CTIME = "1970-01-01 10:00:00:000";
-    const std::string GENERIC_FILEID =
-        "\x28\xb3\x2a\xeb\xb6\x24\xcc\xc2\xbf\xc8\xb0\x2a\xa9\x2b\xfc\xf1";
-    const std::string GENERIC_FOOTID =
-        "\xfa\xbc\xab\x09\xd0\xc8\xd4\x66\xb1\x76\xfb\x83\x1c\xf7\x26\x7e";
-    const std::string FOOT_MAGIC =
-        "\xf8\x5a\x8c\x6a\xde\xf5\xd9\x7e\xec\xe9\x0c\xe3\x75\x8f\x29\x0b";
-    const std::string COMMENT_UNDERLINE =
-        ";------------------------------------------------------------------";
-}
-
-    // ---------------------------------------------------------------------
-    // Worker function for exporting a scene to binary FBX.
-    // Prototyped and registered in Exporter.cpp
-    void ExportSceneFBX (
-        const char* pFile,
-        IOSystem* pIOSystem,
-        const aiScene* pScene,
-        const ExportProperties* pProperties
-    ){
-        // initialize the exporter
-        FBXExporter exporter(pScene, pProperties);
-
-        // perform binary export
-        exporter.ExportBinary(pFile, pIOSystem);
-    }
-
-    // ---------------------------------------------------------------------
-    // Worker function for exporting a scene to ASCII FBX.
-    // Prototyped and registered in Exporter.cpp
-    void ExportSceneFBXA (
-        const char* pFile,
-        IOSystem* pIOSystem,
-        const aiScene* pScene,
-        const ExportProperties* pProperties
-
-    ){
-        // initialize the exporter
-        FBXExporter exporter(pScene, pProperties);
-
-        // perform ascii export
-        exporter.ExportAscii(pFile, pIOSystem);
-    }
-
-} // end of namespace Assimp
-
-FBXExporter::FBXExporter ( const aiScene* pScene, const ExportProperties* pProperties )
-: binary(false)
-, mScene(pScene)
-, mProperties(pProperties)
-, outfile()
-, connections()
-, mesh_uids()
-, material_uids()
-, node_uids() {
-    // will probably need to determine UIDs, connections, etc here.
-    // basically anything that needs to be known
-    // before we start writing sections to the stream.
-}
-
-void FBXExporter::ExportBinary (
-    const char* pFile,
-    IOSystem* pIOSystem
-){
-    // remember that we're exporting in binary mode
-    binary = true;
-
-    // we're not currently using these preferences,
-    // but clang will cry about it if we never touch it.
-    // TODO: some of these might be relevant to export
-    (void)mProperties;
-
-    // open the indicated file for writing (in binary mode)
-    outfile.reset(pIOSystem->Open(pFile,"wb"));
-    if (!outfile) {
-        throw DeadlyExportError(
-            "could not open output .fbx file: " + std::string(pFile)
-        );
-    }
-
-    // first a binary-specific file header
-    WriteBinaryHeader();
-
-    // the rest of the file is in node entries.
-    // we have to serialize each entry before we write to the output,
-    // as the first thing we write is the byte offset of the _next_ entry.
-    // Either that or we can skip back to write the offset when we finish.
-    WriteAllNodes();
-
-    // finally we have a binary footer to the file
-    WriteBinaryFooter();
-
-    // explicitly release file pointer,
-    // so we don't have to rely on class destruction.
-    outfile.reset();
-}
-
-void FBXExporter::ExportAscii (
-    const char* pFile,
-    IOSystem* pIOSystem
-){
-    // remember that we're exporting in ascii mode
-    binary = false;
-
-    // open the indicated file for writing in text mode
-    outfile.reset(pIOSystem->Open(pFile,"wt"));
-    if (!outfile) {
-        throw DeadlyExportError(
-            "could not open output .fbx file: " + std::string(pFile)
-        );
-    }
-
-    // write the ascii header
-    WriteAsciiHeader();
-
-    // write all the sections
-    WriteAllNodes();
-
-    // make sure the file ends with a newline.
-    // note: if the file is opened in text mode,
-    // this should do the right cross-platform thing.
-    outfile->Write("\n", 1, 1);
-
-    // explicitly release file pointer,
-    // so we don't have to rely on class destruction.
-    outfile.reset();
-}
-
-void FBXExporter::WriteAsciiHeader()
-{
-    // basically just a comment at the top of the file
-    std::stringstream head;
-    head << "; FBX " << EXPORT_VERSION_STR << " project file\n";
-    head << "; Created by the Open Asset Import Library (Assimp)\n";
-    head << "; http://assimp.org\n";
-    head << "; -------------------------------------------------\n";
-    const std::string ascii_header = head.str();
-    outfile->Write(ascii_header.c_str(), ascii_header.size(), 1);
-}
-
-void FBXExporter::WriteAsciiSectionHeader(const std::string& title)
-{
-    StreamWriterLE outstream(outfile);
-    std::stringstream s;
-    s << "\n\n; " << title << '\n';
-    s << FBX::COMMENT_UNDERLINE << "\n";
-    outstream.PutString(s.str());
-}
-
-void FBXExporter::WriteBinaryHeader()
-{
-    // first a specific sequence of 23 bytes, always the same
-    const char binary_header[24] = "Kaydara FBX Binary\x20\x20\x00\x1a\x00";
-    outfile->Write(binary_header, 1, 23);
-
-    // then FBX version number, "multiplied" by 1000, as little-endian uint32.
-    // so 7.3 becomes 7300 == 0x841C0000, 7.4 becomes 7400 == 0xE81C0000, etc
-    {
-        StreamWriterLE outstream(outfile);
-        outstream.PutU4(EXPORT_VERSION_INT);
-    } // StreamWriter destructor writes the data to the file
-
-    // after this the node data starts immediately
-    // (probably with the FBXHEaderExtension node)
-}
-
-void FBXExporter::WriteBinaryFooter()
-{
-    outfile->Write(NULL_RECORD.c_str(), NULL_RECORD.size(), 1);
-
-    outfile->Write(GENERIC_FOOTID.c_str(), GENERIC_FOOTID.size(), 1);
-
-    // here some padding is added for alignment to 16 bytes.
-    // if already aligned, the full 16 bytes is added.
-    size_t pos = outfile->Tell();
-    size_t pad = 16 - (pos % 16);
-    for (size_t i = 0; i < pad; ++i) {
-        outfile->Write("\x00", 1, 1);
-    }
-
-    // not sure what this is, but it seems to always be 0 in modern files
-    for (size_t i = 0; i < 4; ++i) {
-        outfile->Write("\x00", 1, 1);
-    }
-
-    // now the file version again
-    {
-        StreamWriterLE outstream(outfile);
-        outstream.PutU4(EXPORT_VERSION_INT);
-    } // StreamWriter destructor writes the data to the file
-
-    // and finally some binary footer added to all files
-    for (size_t i = 0; i < 120; ++i) {
-        outfile->Write("\x00", 1, 1);
-    }
-    outfile->Write(FOOT_MAGIC.c_str(), FOOT_MAGIC.size(), 1);
-}
-
-void FBXExporter::WriteAllNodes ()
-{
-    // header
-    // (and fileid, creation time, creator, if binary)
-    WriteHeaderExtension();
-
-    // global settings
-    WriteGlobalSettings();
-
-    // documents
-    WriteDocuments();
-
-    // references
-    WriteReferences();
-
-    // definitions
-    WriteDefinitions();
-
-    // objects
-    WriteObjects();
-
-    // connections
-    WriteConnections();
-
-    // WriteTakes? (deprecated since at least 2015 (fbx 7.4))
-}
-
-//FBXHeaderExtension top-level node
-void FBXExporter::WriteHeaderExtension ()
-{
-    if (!binary) {
-        // no title, follows directly from the top comment
-    }
-    FBX::Node n("FBXHeaderExtension");
-    StreamWriterLE outstream(outfile);
-    int indent = 0;
-
-    // begin node
-    n.Begin(outstream, binary, indent);
-
-    // write properties
-    // (none)
-
-    // finish properties
-    n.EndProperties(outstream, binary, indent, 0);
-
-    // begin children
-    n.BeginChildren(outstream, binary, indent);
-
-    indent = 1;
-
-    // write child nodes
-    FBX::Node::WritePropertyNode(
-        "FBXHeaderVersion", int32_t(1003), outstream, binary, indent
-    );
-    FBX::Node::WritePropertyNode(
-        "FBXVersion", int32_t(EXPORT_VERSION_INT), outstream, binary, indent
-    );
-    if (binary) {
-        FBX::Node::WritePropertyNode(
-            "EncryptionType", int32_t(0), outstream, binary, indent
-        );
-    }
-
-    FBX::Node CreationTimeStamp("CreationTimeStamp");
-    time_t rawtime;
-    time(&rawtime);
-    struct tm * now = localtime(&rawtime);
-    CreationTimeStamp.AddChild("Version", int32_t(1000));
-    CreationTimeStamp.AddChild("Year", int32_t(now->tm_year + 1900));
-    CreationTimeStamp.AddChild("Month", int32_t(now->tm_mon + 1));
-    CreationTimeStamp.AddChild("Day", int32_t(now->tm_mday));
-    CreationTimeStamp.AddChild("Hour", int32_t(now->tm_hour));
-    CreationTimeStamp.AddChild("Minute", int32_t(now->tm_min));
-    CreationTimeStamp.AddChild("Second", int32_t(now->tm_sec));
-    CreationTimeStamp.AddChild("Millisecond", int32_t(0));
-    CreationTimeStamp.Dump(outstream, binary, indent);
-
-    std::stringstream creator;
-    creator << "Open Asset Import Library (Assimp) " << aiGetVersionMajor()
-            << "." << aiGetVersionMinor() << "." << aiGetVersionRevision();
-    FBX::Node::WritePropertyNode(
-        "Creator", creator.str(), outstream, binary, indent
-    );
-
-    //FBX::Node sceneinfo("SceneInfo");
-    //sceneinfo.AddProperty("GlobalInfo" + FBX::SEPARATOR + "SceneInfo");
-    // not sure if any of this is actually needed,
-    // so just write an empty node for now.
-    //sceneinfo.Dump(outstream, binary, indent);
-
-    indent = 0;
-
-    // finish node
-    n.End(outstream, binary, indent, true);
-
-    // that's it for FBXHeaderExtension...
-    if (!binary) { return; }
-
-    // but binary files also need top-level FileID, CreationTime, Creator:
-    std::vector<uint8_t> raw(GENERIC_FILEID.size());
-    for (size_t i = 0; i < GENERIC_FILEID.size(); ++i) {
-        raw[i] = uint8_t(GENERIC_FILEID[i]);
-    }
-    FBX::Node::WritePropertyNode(
-        "FileId", raw, outstream, binary, indent
-    );
-    FBX::Node::WritePropertyNode(
-        "CreationTime", GENERIC_CTIME, outstream, binary, indent
-    );
-    FBX::Node::WritePropertyNode(
-        "Creator", creator.str(), outstream, binary, indent
-    );
-}
-
-void FBXExporter::WriteGlobalSettings ()
-{
-    if (!binary) {
-        // no title, follows directly from the header extension
-    }
-    FBX::Node gs("GlobalSettings");
-    gs.AddChild("Version", int32_t(1000));
-
-    FBX::Node p("Properties70");
-    p.AddP70int("UpAxis", 1);
-    p.AddP70int("UpAxisSign", 1);
-    p.AddP70int("FrontAxis", 2);
-    p.AddP70int("FrontAxisSign", 1);
-    p.AddP70int("CoordAxis", 0);
-    p.AddP70int("CoordAxisSign", 1);
-    p.AddP70int("OriginalUpAxis", 1);
-    p.AddP70int("OriginalUpAxisSign", 1);
-    p.AddP70double("UnitScaleFactor", 1.0);
-    p.AddP70double("OriginalUnitScaleFactor", 1.0);
-    p.AddP70color("AmbientColor", 0.0, 0.0, 0.0);
-    p.AddP70string("DefaultCamera", "Producer Perspective");
-    p.AddP70enum("TimeMode", 11);
-    p.AddP70enum("TimeProtocol", 2);
-    p.AddP70enum("SnapOnFrameMode", 0);
-    p.AddP70time("TimeSpanStart", 0); // TODO: animation support
-    p.AddP70time("TimeSpanStop", FBX::SECOND); // TODO: animation support
-    p.AddP70double("CustomFrameRate", -1.0);
-    p.AddP70("TimeMarker", "Compound", "", ""); // not sure what this is
-    p.AddP70int("CurrentTimeMarker", -1);
-    gs.AddChild(p);
-
-    gs.Dump(outfile, binary, 0);
-}
-
-void FBXExporter::WriteDocuments ()
-{
-    if (!binary) {
-        WriteAsciiSectionHeader("Documents Description");
-    }
-    
-    // not sure what the use of multiple documents would be,
-    // or whether any end-application supports it
-    FBX::Node docs("Documents");
-    docs.AddChild("Count", int32_t(1));
-    FBX::Node doc("Document");
-
-    // generate uid
-    int64_t uid = generate_uid();
-    doc.AddProperties(uid, "", "Scene");
-    FBX::Node p("Properties70");
-    p.AddP70("SourceObject", "object", "", ""); // what is this even for?
-    p.AddP70string("ActiveAnimStackName", ""); // should do this properly?
-    doc.AddChild(p);
-
-    // UID for root node in scene hierarchy.
-    // always set to 0 in the case of a single document.
-    // not sure what happens if more than one document exists,
-    // but that won't matter to us as we're exporting a single scene.
-    doc.AddChild("RootNode", int64_t(0));
-
-    docs.AddChild(doc);
-    docs.Dump(outfile, binary, 0);
-}
-
-void FBXExporter::WriteReferences ()
-{
-    if (!binary) {
-        WriteAsciiSectionHeader("Document References");
-    }
-    // always empty for now.
-    // not really sure what this is for.
-    FBX::Node n("References");
-    n.force_has_children = true;
-    n.Dump(outfile, binary, 0);
-}
-
-
-// ---------------------------------------------------------------
-// some internal helper functions used for writing the definitions
-// (before any actual data is written)
-// ---------------------------------------------------------------
-
-size_t count_nodes(const aiNode* n) {
-    size_t count = 1;
-    for (size_t i = 0; i < n->mNumChildren; ++i) {
-        count += count_nodes(n->mChildren[i]);
-    }
-    return count;
-}
-
-bool has_phong_mat(const aiScene* scene)
-{
-    // just search for any material with a shininess exponent
-    for (size_t i = 0; i < scene->mNumMaterials; ++i) {
-        aiMaterial* mat = scene->mMaterials[i];
-        float shininess = 0;
-        mat->Get(AI_MATKEY_SHININESS, shininess);
-        if (shininess > 0) {
-            return true;
-        }
-    }
-    return false;
-}
-
-size_t count_images(const aiScene* scene) {
-    std::unordered_set<std::string> images;
-    aiString texpath;
-    for (size_t i = 0; i < scene->mNumMaterials; ++i) {
-        aiMaterial* mat = scene->mMaterials[i];
-        for (
-            size_t tt = aiTextureType_DIFFUSE;
-            tt < aiTextureType_UNKNOWN;
-            ++tt
-        ){
-            const aiTextureType textype = static_cast<aiTextureType>(tt);
-            const size_t texcount = mat->GetTextureCount(textype);
-            for (unsigned int j = 0; j < texcount; ++j) {
-                mat->GetTexture(textype, j, &texpath);
-                images.insert(std::string(texpath.C_Str()));
-            }
-        }
-    }
-    return images.size();
-}
-
-size_t count_textures(const aiScene* scene) {
-    size_t count = 0;
-    for (size_t i = 0; i < scene->mNumMaterials; ++i) {
-        aiMaterial* mat = scene->mMaterials[i];
-        for (
-            size_t tt = aiTextureType_DIFFUSE;
-            tt < aiTextureType_UNKNOWN;
-            ++tt
-        ){
-            // TODO: handle layered textures
-            if (mat->GetTextureCount(static_cast<aiTextureType>(tt)) > 0) {
-                count += 1;
-            }
-        }
-    }
-    return count;
-}
-
-size_t count_deformers(const aiScene* scene) {
-    size_t count = 0;
-    for (size_t i = 0; i < scene->mNumMeshes; ++i) {
-        const size_t n = scene->mMeshes[i]->mNumBones;
-        if (n) {
-            // 1 main deformer, 1 subdeformer per bone
-            count += n + 1;
-        }
-    }
-    return count;
-}
-
-void FBXExporter::WriteDefinitions ()
-{
-    // basically this is just bookkeeping:
-    // determining how many of each type of object there are
-    // and specifying the base properties to use when otherwise unspecified.
-
-    // ascii section header
-    if (!binary) {
-        WriteAsciiSectionHeader("Object definitions");
-    }
-
-    // we need to count the objects
-    int32_t count;
-    int32_t total_count = 0;
-
-    // and store them
-    std::vector<FBX::Node> object_nodes;
-    FBX::Node n, pt, p;
-
-    // GlobalSettings
-    // this seems to always be here in Maya exports
-    n = FBX::Node("ObjectType", "GlobalSettings");
-    count = 1;
-    n.AddChild("Count", count);
-    object_nodes.push_back(n);
-    total_count += count;
-
-    // AnimationStack / FbxAnimStack
-    // this seems to always be here in Maya exports,
-    // but no harm seems to come of leaving it out.
-    count = mScene->mNumAnimations;
-    if (count) {
-        n = FBX::Node("ObjectType", "AnimationStack");
-        n.AddChild("Count", count);
-        pt = FBX::Node("PropertyTemplate", "FbxAnimStack");
-        p = FBX::Node("Properties70");
-        p.AddP70string("Description", "");
-        p.AddP70time("LocalStart", 0);
-        p.AddP70time("LocalStop", 0);
-        p.AddP70time("ReferenceStart", 0);
-        p.AddP70time("ReferenceStop", 0);
-        pt.AddChild(p);
-        n.AddChild(pt);
-        object_nodes.push_back(n);
-        total_count += count;
-    }
-
-    // AnimationLayer / FbxAnimLayer
-    // this seems to always be here in Maya exports,
-    // but no harm seems to come of leaving it out.
-    // Assimp doesn't support animation layers,
-    // so there will be one per aiAnimation
-    count = mScene->mNumAnimations;
-    if (count) {
-        n = FBX::Node("ObjectType", "AnimationLayer");
-        n.AddChild("Count", count);
-        pt = FBX::Node("PropertyTemplate", "FBXAnimLayer");
-        p = FBX::Node("Properties70");
-        p.AddP70("Weight", "Number", "", "A", double(100));
-        p.AddP70bool("Mute", 0);
-        p.AddP70bool("Solo", 0);
-        p.AddP70bool("Lock", 0);
-        p.AddP70color("Color", 0.8, 0.8, 0.8);
-        p.AddP70("BlendMode", "enum", "", "", int32_t(0));
-        p.AddP70("RotationAccumulationMode", "enum", "", "", int32_t(0));
-        p.AddP70("ScaleAccumulationMode", "enum", "", "", int32_t(0));
-        p.AddP70("BlendModeBypass", "ULongLong", "", "", int64_t(0));
-        pt.AddChild(p);
-        n.AddChild(pt);
-        object_nodes.push_back(n);
-        total_count += count;
-    }
-
-    // NodeAttribute
-    // this is completely absurd.
-    // there can only be one "NodeAttribute" template,
-    // but FbxSkeleton, FbxCamera, FbxLight all are "NodeAttributes".
-    // so if only one exists we should set the template for that,
-    // otherwise... we just pick one :/.
-    // the others have to set all their properties every instance,
-    // because there's no template.
-    count = 1; // TODO: select properly
-    if (count) {
-        // FbxSkeleton
-        n = FBX::Node("ObjectType", "NodeAttribute");
-        n.AddChild("Count", count);
-        pt = FBX::Node("PropertyTemplate", "FbxSkeleton");
-        p = FBX::Node("Properties70");
-        p.AddP70color("Color", 0.8, 0.8, 0.8);
-        p.AddP70double("Size", 33.333333333333);
-        p.AddP70("LimbLength", "double", "Number", "H", double(1));
-        // note: not sure what the "H" flag is for - hidden?
-        pt.AddChild(p);
-        n.AddChild(pt);
-        object_nodes.push_back(n);
-        total_count += count;
-    }
-
-    // Model / FbxNode
-    // <~~ node hierarchy
-    count = int32_t(count_nodes(mScene->mRootNode)) - 1; // (not counting root node)
-    if (count) {
-        n = FBX::Node("ObjectType", "Model");
-        n.AddChild("Count", count);
-        pt = FBX::Node("PropertyTemplate", "FbxNode");
-        p = FBX::Node("Properties70");
-        p.AddP70enum("QuaternionInterpolate", 0);
-        p.AddP70vector("RotationOffset", 0.0, 0.0, 0.0);
-        p.AddP70vector("RotationPivot", 0.0, 0.0, 0.0);
-        p.AddP70vector("ScalingOffset", 0.0, 0.0, 0.0);
-        p.AddP70vector("ScalingPivot", 0.0, 0.0, 0.0);
-        p.AddP70bool("TranslationActive", 0);
-        p.AddP70vector("TranslationMin", 0.0, 0.0, 0.0);
-        p.AddP70vector("TranslationMax", 0.0, 0.0, 0.0);
-        p.AddP70bool("TranslationMinX", 0);
-        p.AddP70bool("TranslationMinY", 0);
-        p.AddP70bool("TranslationMinZ", 0);
-        p.AddP70bool("TranslationMaxX", 0);
-        p.AddP70bool("TranslationMaxY", 0);
-        p.AddP70bool("TranslationMaxZ", 0);
-        p.AddP70enum("RotationOrder", 0);
-        p.AddP70bool("RotationSpaceForLimitOnly", 0);
-        p.AddP70double("RotationStiffnessX", 0.0);
-        p.AddP70double("RotationStiffnessY", 0.0);
-        p.AddP70double("RotationStiffnessZ", 0.0);
-        p.AddP70double("AxisLen", 10.0);
-        p.AddP70vector("PreRotation", 0.0, 0.0, 0.0);
-        p.AddP70vector("PostRotation", 0.0, 0.0, 0.0);
-        p.AddP70bool("RotationActive", 0);
-        p.AddP70vector("RotationMin", 0.0, 0.0, 0.0);
-        p.AddP70vector("RotationMax", 0.0, 0.0, 0.0);
-        p.AddP70bool("RotationMinX", 0);
-        p.AddP70bool("RotationMinY", 0);
-        p.AddP70bool("RotationMinZ", 0);
-        p.AddP70bool("RotationMaxX", 0);
-        p.AddP70bool("RotationMaxY", 0);
-        p.AddP70bool("RotationMaxZ", 0);
-        p.AddP70enum("InheritType", 0);
-        p.AddP70bool("ScalingActive", 0);
-        p.AddP70vector("ScalingMin", 0.0, 0.0, 0.0);
-        p.AddP70vector("ScalingMax", 1.0, 1.0, 1.0);
-        p.AddP70bool("ScalingMinX", 0);
-        p.AddP70bool("ScalingMinY", 0);
-        p.AddP70bool("ScalingMinZ", 0);
-        p.AddP70bool("ScalingMaxX", 0);
-        p.AddP70bool("ScalingMaxY", 0);
-        p.AddP70bool("ScalingMaxZ", 0);
-        p.AddP70vector("GeometricTranslation", 0.0, 0.0, 0.0);
-        p.AddP70vector("GeometricRotation", 0.0, 0.0, 0.0);
-        p.AddP70vector("GeometricScaling", 1.0, 1.0, 1.0);
-        p.AddP70double("MinDampRangeX", 0.0);
-        p.AddP70double("MinDampRangeY", 0.0);
-        p.AddP70double("MinDampRangeZ", 0.0);
-        p.AddP70double("MaxDampRangeX", 0.0);
-        p.AddP70double("MaxDampRangeY", 0.0);
-        p.AddP70double("MaxDampRangeZ", 0.0);
-        p.AddP70double("MinDampStrengthX", 0.0);
-        p.AddP70double("MinDampStrengthY", 0.0);
-        p.AddP70double("MinDampStrengthZ", 0.0);
-        p.AddP70double("MaxDampStrengthX", 0.0);
-        p.AddP70double("MaxDampStrengthY", 0.0);
-        p.AddP70double("MaxDampStrengthZ", 0.0);
-        p.AddP70double("PreferedAngleX", 0.0);
-        p.AddP70double("PreferedAngleY", 0.0);
-        p.AddP70double("PreferedAngleZ", 0.0);
-        p.AddP70("LookAtProperty", "object", "", "");
-        p.AddP70("UpVectorProperty", "object", "", "");
-        p.AddP70bool("Show", 1);
-        p.AddP70bool("NegativePercentShapeSupport", 1);
-        p.AddP70int("DefaultAttributeIndex", -1);
-        p.AddP70bool("Freeze", 0);
-        p.AddP70bool("LODBox", 0);
-        p.AddP70(
-            "Lcl Translation", "Lcl Translation", "", "A",
-            double(0), double(0), double(0)
-        );
-        p.AddP70(
-            "Lcl Rotation", "Lcl Rotation", "", "A",
-            double(0), double(0), double(0)
-        );
-        p.AddP70(
-            "Lcl Scaling", "Lcl Scaling", "", "A",
-            double(1), double(1), double(1)
-        );
-        p.AddP70("Visibility", "Visibility", "", "A", double(1));
-        p.AddP70(
-            "Visibility Inheritance", "Visibility Inheritance", "", "",
-            int32_t(1)
-        );
-        pt.AddChild(p);
-        n.AddChild(pt);
-        object_nodes.push_back(n);
-        total_count += count;
-    }
-
-    // Geometry / FbxMesh
-    // <~~ aiMesh
-    count = mScene->mNumMeshes;
-    if (count) {
-        n = FBX::Node("ObjectType", "Geometry");
-        n.AddChild("Count", count);
-        pt = FBX::Node("PropertyTemplate", "FbxMesh");
-        p = FBX::Node("Properties70");
-        p.AddP70color("Color", 0, 0, 0);
-        p.AddP70vector("BBoxMin", 0, 0, 0);
-        p.AddP70vector("BBoxMax", 0, 0, 0);
-        p.AddP70bool("Primary Visibility", 1);
-        p.AddP70bool("Casts Shadows", 1);
-        p.AddP70bool("Receive Shadows", 1);
-        pt.AddChild(p);
-        n.AddChild(pt);
-        object_nodes.push_back(n);
-        total_count += count;
-    }
-
-    // Material / FbxSurfacePhong, FbxSurfaceLambert, FbxSurfaceMaterial
-    // <~~ aiMaterial
-    // basically if there's any phong material this is defined as phong,
-    // and otherwise lambert.
-    // More complex materials cause a bare-bones FbxSurfaceMaterial definition
-    // and are treated specially, as they're not really supported by FBX.
-    // TODO: support Maya's Stingray PBS material
-    count = mScene->mNumMaterials;
-    if (count) {
-        bool has_phong = has_phong_mat(mScene);
-        n = FBX::Node("ObjectType", "Material");
-        n.AddChild("Count", count);
-        pt = FBX::Node("PropertyTemplate");
-        if (has_phong) {
-            pt.AddProperty("FbxSurfacePhong");
-        } else {
-            pt.AddProperty("FbxSurfaceLambert");
-        }
-        p = FBX::Node("Properties70");
-        if (has_phong) {
-            p.AddP70string("ShadingModel", "Phong");
-        } else {
-            p.AddP70string("ShadingModel", "Lambert");
-        }
-        p.AddP70bool("MultiLayer", 0);
-        p.AddP70colorA("EmissiveColor", 0.0, 0.0, 0.0);
-        p.AddP70numberA("EmissiveFactor", 1.0);
-        p.AddP70colorA("AmbientColor", 0.2, 0.2, 0.2);
-        p.AddP70numberA("AmbientFactor", 1.0);
-        p.AddP70colorA("DiffuseColor", 0.8, 0.8, 0.8);
-        p.AddP70numberA("DiffuseFactor", 1.0);
-        p.AddP70vector("Bump", 0.0, 0.0, 0.0);
-        p.AddP70vector("NormalMap", 0.0, 0.0, 0.0);
-        p.AddP70double("BumpFactor", 1.0);
-        p.AddP70colorA("TransparentColor", 0.0, 0.0, 0.0);
-        p.AddP70numberA("TransparencyFactor", 0.0);
-        p.AddP70color("DisplacementColor", 0.0, 0.0, 0.0);
-        p.AddP70double("DisplacementFactor", 1.0);
-        p.AddP70color("VectorDisplacementColor", 0.0, 0.0, 0.0);
-        p.AddP70double("VectorDisplacementFactor", 1.0);
-        if (has_phong) {
-            p.AddP70colorA("SpecularColor", 0.2, 0.2, 0.2);
-            p.AddP70numberA("SpecularFactor", 1.0);
-            p.AddP70numberA("ShininessExponent", 20.0);
-            p.AddP70colorA("ReflectionColor", 0.0, 0.0, 0.0);
-            p.AddP70numberA("ReflectionFactor", 1.0);
-        }
-        pt.AddChild(p);
-        n.AddChild(pt);
-        object_nodes.push_back(n);
-        total_count += count;
-    }
-
-    // Video / FbxVideo
-    // one for each image file.
-    count = int32_t(count_images(mScene));
-    if (count) {
-        n = FBX::Node("ObjectType", "Video");
-        n.AddChild("Count", count);
-        pt = FBX::Node("PropertyTemplate", "FbxVideo");
-        p = FBX::Node("Properties70");
-        p.AddP70bool("ImageSequence", 0);
-        p.AddP70int("ImageSequenceOffset", 0);
-        p.AddP70double("FrameRate", 0.0);
-        p.AddP70int("LastFrame", 0);
-        p.AddP70int("Width", 0);
-        p.AddP70int("Height", 0);
-        p.AddP70("Path", "KString", "XRefUrl", "", "");
-        p.AddP70int("StartFrame", 0);
-        p.AddP70int("StopFrame", 0);
-        p.AddP70double("PlaySpeed", 0.0);
-        p.AddP70time("Offset", 0);
-        p.AddP70enum("InterlaceMode", 0);
-        p.AddP70bool("FreeRunning", 0);
-        p.AddP70bool("Loop", 0);
-        p.AddP70enum("AccessMode", 0);
-        pt.AddChild(p);
-        n.AddChild(pt);
-        object_nodes.push_back(n);
-        total_count += count;
-    }
-
-    // Texture / FbxFileTexture
-    // <~~ aiTexture
-    count = int32_t(count_textures(mScene));
-    if (count) {
-        n = FBX::Node("ObjectType", "Texture");
-        n.AddChild("Count", count);
-        pt = FBX::Node("PropertyTemplate", "FbxFileTexture");
-        p = FBX::Node("Properties70");
-        p.AddP70enum("TextureTypeUse", 0);
-        p.AddP70numberA("Texture alpha", 1.0);
-        p.AddP70enum("CurrentMappingType", 0);
-        p.AddP70enum("WrapModeU", 0);
-        p.AddP70enum("WrapModeV", 0);
-        p.AddP70bool("UVSwap", 0);
-        p.AddP70bool("PremultiplyAlpha", 1);
-        p.AddP70vectorA("Translation", 0.0, 0.0, 0.0);
-        p.AddP70vectorA("Rotation", 0.0, 0.0, 0.0);
-        p.AddP70vectorA("Scaling", 1.0, 1.0, 1.0);
-        p.AddP70vector("TextureRotationPivot", 0.0, 0.0, 0.0);
-        p.AddP70vector("TextureScalingPivot", 0.0, 0.0, 0.0);
-        p.AddP70enum("CurrentTextureBlendMode", 1);
-        p.AddP70string("UVSet", "default");
-        p.AddP70bool("UseMaterial", 0);
-        p.AddP70bool("UseMipMap", 0);
-        pt.AddChild(p);
-        n.AddChild(pt);
-        object_nodes.push_back(n);
-        total_count += count;
-    }
-
-    // AnimationCurveNode / FbxAnimCurveNode
-    count = mScene->mNumAnimations * 3;
-    if (count) {
-        n = FBX::Node("ObjectType", "AnimationCurveNode");
-        n.AddChild("Count", count);
-        pt = FBX::Node("PropertyTemplate", "FbxAnimCurveNode");
-        p = FBX::Node("Properties70");
-        p.AddP70("d", "Compound", "", "");
-        pt.AddChild(p);
-        n.AddChild(pt);
-        object_nodes.push_back(n);
-        total_count += count;
-    }
-
-    // AnimationCurve / FbxAnimCurve
-    count = mScene->mNumAnimations * 9;
-    if (count) {
-        n = FBX::Node("ObjectType", "AnimationCurve");
-        n.AddChild("Count", count);
-        object_nodes.push_back(n);
-        total_count += count;
-    }
-
-    // Pose
-    count = 0;
-    for (size_t i = 0; i < mScene->mNumMeshes; ++i) {
-        aiMesh* mesh = mScene->mMeshes[i];
-        if (mesh->HasBones()) { ++count; }
-    }
-    if (count) {
-        n = FBX::Node("ObjectType", "Pose");
-        n.AddChild("Count", count);
-        object_nodes.push_back(n);
-        total_count += count;
-    }
-
-    // Deformer
-    count = int32_t(count_deformers(mScene));
-    if (count) {
-        n = FBX::Node("ObjectType", "Deformer");
-        n.AddChild("Count", count);
-        object_nodes.push_back(n);
-        total_count += count;
-    }
-
-    // (template)
-    count = 0;
-    if (count) {
-        n = FBX::Node("ObjectType", "");
-        n.AddChild("Count", count);
-        pt = FBX::Node("PropertyTemplate", "");
-        p = FBX::Node("Properties70");
-        pt.AddChild(p);
-        n.AddChild(pt);
-        object_nodes.push_back(n);
-        total_count += count;
-    }
-
-    // now write it all
-    FBX::Node defs("Definitions");
-    defs.AddChild("Version", int32_t(100));
-    defs.AddChild("Count", int32_t(total_count));
-    for (auto &n : object_nodes) { defs.AddChild(n); }
-    defs.Dump(outfile, binary, 0);
-}
-
-
-// -------------------------------------------------------------------
-// some internal helper functions used for writing the objects section
-// (which holds the actual data)
-// -------------------------------------------------------------------
-
-aiNode* get_node_for_mesh(unsigned int meshIndex, aiNode* node)
-{
-    for (size_t i = 0; i < node->mNumMeshes; ++i) {
-        if (node->mMeshes[i] == meshIndex) {
-            return node;
-        }
-    }
-    for (size_t i = 0; i < node->mNumChildren; ++i) {
-        aiNode* ret = get_node_for_mesh(meshIndex, node->mChildren[i]);
-        if (ret) { return ret; }
-    }
-    return nullptr;
-}
-
-aiMatrix4x4 get_world_transform(const aiNode* node, const aiScene* scene)
-{
-    std::vector<const aiNode*> node_chain;
-    while (node != scene->mRootNode) {
-        node_chain.push_back(node);
-        node = node->mParent;
-    }
-    aiMatrix4x4 transform;
-    for (auto n = node_chain.rbegin(); n != node_chain.rend(); ++n) {
-        transform *= (*n)->mTransformation;
-    }
-    return transform;
-}
-
-int64_t to_ktime(double ticks, const aiAnimation* anim) {
-    if (anim->mTicksPerSecond <= 0) {
-        return static_cast<int64_t>(ticks) * FBX::SECOND;
-    }
-    return (static_cast<int64_t>(ticks) / static_cast<int64_t>(anim->mTicksPerSecond)) * FBX::SECOND;
-}
-
-int64_t to_ktime(double time) {
-    return (static_cast<int64_t>(time * FBX::SECOND));
-}
-
-void FBXExporter::WriteObjects ()
-{
-    if (!binary) {
-        WriteAsciiSectionHeader("Object properties");
-    }
-    // numbers should match those given in definitions! make sure to check
-    StreamWriterLE outstream(outfile);
-    FBX::Node object_node("Objects");
-    int indent = 0;
-    object_node.Begin(outstream, binary, indent);
-    object_node.EndProperties(outstream, binary, indent);
-    object_node.BeginChildren(outstream, binary, indent);
-
-    bool bJoinIdenticalVertices = mProperties->GetPropertyBool("bJoinIdenticalVertices", true);
-    std::vector<std::vector<int32_t>> vVertexIndice;//save vertex_indices as it is needed later
-
-    // geometry (aiMesh)
-    mesh_uids.clear();
-    indent = 1;
-    for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) {
-        // it's all about this mesh
-        aiMesh* m = mScene->mMeshes[mi];
-
-        // start the node record
-        FBX::Node n("Geometry");
-        int64_t uid = generate_uid();
-        mesh_uids.push_back(uid);
-        n.AddProperty(uid);
-        n.AddProperty(FBX::SEPARATOR + "Geometry");
-        n.AddProperty("Mesh");
-        n.Begin(outstream, binary, indent);
-        n.DumpProperties(outstream, binary, indent);
-        n.EndProperties(outstream, binary, indent);
-        n.BeginChildren(outstream, binary, indent);
-        indent = 2;
-
-        // output vertex data - each vertex should be unique (probably)
-        std::vector<double> flattened_vertices;
-        // index of original vertex in vertex data vector
-        std::vector<int32_t> vertex_indices;
-        // map of vertex value to its index in the data vector
-        std::map<aiVector3D,size_t> index_by_vertex_value;
-        if(bJoinIdenticalVertices){
-            int32_t index = 0;
-            for (size_t vi = 0; vi < m->mNumVertices; ++vi) {
-                aiVector3D vtx = m->mVertices[vi];
-                auto elem = index_by_vertex_value.find(vtx);
-                if (elem == index_by_vertex_value.end()) {
-                    vertex_indices.push_back(index);
-                    index_by_vertex_value[vtx] = index;
-                    flattened_vertices.push_back(vtx[0]);
-                    flattened_vertices.push_back(vtx[1]);
-                    flattened_vertices.push_back(vtx[2]);
-                    ++index;
-                } else {
-                    vertex_indices.push_back(int32_t(elem->second));
-                }
-            }
-        }
-        else { // do not join vertex, respect the export flag
-            vertex_indices.resize(m->mNumVertices);
-            std::iota(vertex_indices.begin(), vertex_indices.end(), 0);
-            for(unsigned int v = 0; v < m->mNumVertices; ++ v) {
-                aiVector3D vtx = m->mVertices[v];
-                flattened_vertices.push_back(vtx.x);
-                flattened_vertices.push_back(vtx.y);
-                flattened_vertices.push_back(vtx.z);
-            }
-        }
-        vVertexIndice.push_back(vertex_indices);
-
-        FBX::Node::WritePropertyNode(
-            "Vertices", flattened_vertices, outstream, binary, indent
-        );
-
-        // output polygon data as a flattened array of vertex indices.
-        // the last vertex index of each polygon is negated and - 1
-        std::vector<int32_t> polygon_data;
-        for (size_t fi = 0; fi < m->mNumFaces; ++fi) {
-            const aiFace &f = m->mFaces[fi];
-            for (size_t pvi = 0; pvi < f.mNumIndices - 1; ++pvi) {
-                polygon_data.push_back(vertex_indices[f.mIndices[pvi]]);
-            }
-            polygon_data.push_back(
-                -1 - vertex_indices[f.mIndices[f.mNumIndices-1]]
-            );
-        }
-        FBX::Node::WritePropertyNode(
-            "PolygonVertexIndex", polygon_data, outstream, binary, indent
-        );
-
-        // here could be edges but they're insane.
-        // it's optional anyway, so let's ignore it.
-
-        FBX::Node::WritePropertyNode(
-            "GeometryVersion", int32_t(124), outstream, binary, indent
-        );
-
-        // normals, if any
-        if (m->HasNormals()) {
-            FBX::Node normals("LayerElementNormal", int32_t(0));
-            normals.Begin(outstream, binary, indent);
-            normals.DumpProperties(outstream, binary, indent);
-            normals.EndProperties(outstream, binary, indent);
-            normals.BeginChildren(outstream, binary, indent);
-            indent = 3;
-            FBX::Node::WritePropertyNode(
-                "Version", int32_t(101), outstream, binary, indent
-            );
-            FBX::Node::WritePropertyNode(
-                "Name", "", outstream, binary, indent
-            );
-            FBX::Node::WritePropertyNode(
-                "MappingInformationType", "ByPolygonVertex",
-                outstream, binary, indent
-            );
-            // TODO: vertex-normals or indexed normals when appropriate
-            FBX::Node::WritePropertyNode(
-                "ReferenceInformationType", "Direct",
-                outstream, binary, indent
-            );
-            std::vector<double> normal_data;
-            normal_data.reserve(3 * polygon_data.size());
-            for (size_t fi = 0; fi < m->mNumFaces; ++fi) {
-                const aiFace &f = m->mFaces[fi];
-                for (size_t pvi = 0; pvi < f.mNumIndices; ++pvi) {
-                    const aiVector3D &n = m->mNormals[f.mIndices[pvi]];
-                    normal_data.push_back(n.x);
-                    normal_data.push_back(n.y);
-                    normal_data.push_back(n.z);
-                }
-            }
-            FBX::Node::WritePropertyNode(
-                "Normals", normal_data, outstream, binary, indent
-            );
-            // note: version 102 has a NormalsW also... not sure what it is,
-            // so we can stick with version 101 for now.
-            indent = 2;
-            normals.End(outstream, binary, indent, true);
-        }
-
-        // colors, if any
-        // TODO only one color channel currently
-        const int32_t colorChannelIndex = 0;
-        if (m->HasVertexColors(colorChannelIndex)) {
-            FBX::Node vertexcolors("LayerElementColor", int32_t(colorChannelIndex));
-            vertexcolors.Begin(outstream, binary, indent);
-            vertexcolors.DumpProperties(outstream, binary, indent);
-            vertexcolors.EndProperties(outstream, binary, indent);
-            vertexcolors.BeginChildren(outstream, binary, indent);
-            indent = 3;
-            FBX::Node::WritePropertyNode(
-                "Version", int32_t(101), outstream, binary, indent
-            );
-            char layerName[8];
-            sprintf(layerName, "COLOR_%d", colorChannelIndex);
-            FBX::Node::WritePropertyNode(
-                "Name", (const char*)layerName, outstream, binary, indent
-            );
-            FBX::Node::WritePropertyNode(
-                "MappingInformationType", "ByPolygonVertex",
-                outstream, binary, indent
-            );
-            FBX::Node::WritePropertyNode(
-                "ReferenceInformationType", "Direct",
-                outstream, binary, indent
-            );
-            std::vector<double> color_data;
-            color_data.reserve(4 * polygon_data.size());
-            for (size_t fi = 0; fi < m->mNumFaces; ++fi) {
-                const aiFace &f = m->mFaces[fi];
-                for (size_t pvi = 0; pvi < f.mNumIndices; ++pvi) {
-                    const aiColor4D &c = m->mColors[colorChannelIndex][f.mIndices[pvi]];
-                    color_data.push_back(c.r);
-                    color_data.push_back(c.g);
-                    color_data.push_back(c.b);
-                    color_data.push_back(c.a);
-                }
-            }
-            FBX::Node::WritePropertyNode(
-                "Colors", color_data, outstream, binary, indent
-            );
-            indent = 2;
-            vertexcolors.End(outstream, binary, indent, true);
-        }
-        
-        // uvs, if any
-        for (size_t uvi = 0; uvi < m->GetNumUVChannels(); ++uvi) {
-            if (m->mNumUVComponents[uvi] > 2) {
-                // FBX only supports 2-channel UV maps...
-                // or at least i'm not sure how to indicate a different number
-                std::stringstream err;
-                err << "Only 2-channel UV maps supported by FBX,";
-                err << " but mesh " << mi;
-                if (m->mName.length) {
-                    err << " (" << m->mName.C_Str() << ")";
-                }
-                err << " UV map " << uvi;
-                err << " has " << m->mNumUVComponents[uvi];
-                err << " components! Data will be preserved,";
-                err << " but may be incorrectly interpreted on load.";
-                ASSIMP_LOG_WARN(err.str());
-            }
-            FBX::Node uv("LayerElementUV", int32_t(uvi));
-            uv.Begin(outstream, binary, indent);
-            uv.DumpProperties(outstream, binary, indent);
-            uv.EndProperties(outstream, binary, indent);
-            uv.BeginChildren(outstream, binary, indent);
-            indent = 3;
-            FBX::Node::WritePropertyNode(
-                "Version", int32_t(101), outstream, binary, indent
-            );
-            // it doesn't seem like assimp keeps the uv map name,
-            // so just leave it blank.
-            FBX::Node::WritePropertyNode(
-                "Name", "", outstream, binary, indent
-            );
-            FBX::Node::WritePropertyNode(
-                "MappingInformationType", "ByPolygonVertex",
-                outstream, binary, indent
-            );
-            FBX::Node::WritePropertyNode(
-                "ReferenceInformationType", "IndexToDirect",
-                outstream, binary, indent
-            );
-
-            std::vector<double> uv_data;
-            std::vector<int32_t> uv_indices;
-            std::map<aiVector3D,int32_t> index_by_uv;
-            int32_t index = 0;
-            for (size_t fi = 0; fi < m->mNumFaces; ++fi) {
-                const aiFace &f = m->mFaces[fi];
-                for (size_t pvi = 0; pvi < f.mNumIndices; ++pvi) {
-                    const aiVector3D &uv =
-                        m->mTextureCoords[uvi][f.mIndices[pvi]];
-                    auto elem = index_by_uv.find(uv);
-                    if (elem == index_by_uv.end()) {
-                        index_by_uv[uv] = index;
-                        uv_indices.push_back(index);
-                        for (unsigned int x = 0; x < m->mNumUVComponents[uvi]; ++x) {
-                            uv_data.push_back(uv[x]);
-                        }
-                        ++index;
-                    } else {
-                        uv_indices.push_back(elem->second);
-                    }
-                }
-            }
-            FBX::Node::WritePropertyNode(
-                "UV", uv_data, outstream, binary, indent
-            );
-            FBX::Node::WritePropertyNode(
-                "UVIndex", uv_indices, outstream, binary, indent
-            );
-            indent = 2;
-            uv.End(outstream, binary, indent, true);
-        }
-
-        // i'm not really sure why this material section exists,
-        // as the material is linked via "Connections".
-        // it seems to always have the same "0" value.
-        FBX::Node mat("LayerElementMaterial", int32_t(0));
-        mat.AddChild("Version", int32_t(101));
-        mat.AddChild("Name", "");
-        mat.AddChild("MappingInformationType", "AllSame");
-        mat.AddChild("ReferenceInformationType", "IndexToDirect");
-        std::vector<int32_t> mat_indices = {0};
-        mat.AddChild("Materials", mat_indices);
-        mat.Dump(outstream, binary, indent);
-
-        // finally we have the layer specifications,
-        // which select the normals / UV set / etc to use.
-        // TODO: handle multiple uv sets correctly?
-        FBX::Node layer("Layer", int32_t(0));
-        layer.AddChild("Version", int32_t(100));
-        FBX::Node le("LayerElement");
-        le.AddChild("Type", "LayerElementNormal");
-        le.AddChild("TypedIndex", int32_t(0));
-        layer.AddChild(le);
-        // TODO only 1 color channel currently
-        le = FBX::Node("LayerElement");
-        le.AddChild("Type", "LayerElementColor");
-        le.AddChild("TypedIndex", int32_t(0));
-        layer.AddChild(le);
-        le = FBX::Node("LayerElement");
-        le.AddChild("Type", "LayerElementMaterial");
-        le.AddChild("TypedIndex", int32_t(0));
-        layer.AddChild(le);
-        le = FBX::Node("LayerElement");
-        le.AddChild("Type", "LayerElementUV");
-        le.AddChild("TypedIndex", int32_t(0));
-        layer.AddChild(le);
-        layer.Dump(outstream, binary, indent);
-
-        for(unsigned int lr = 1; lr < m->GetNumUVChannels(); ++ lr)
-        {
-            FBX::Node layerExtra("Layer", int32_t(lr));
-            layerExtra.AddChild("Version", int32_t(100));
-            FBX::Node leExtra("LayerElement");
-            leExtra.AddChild("Type", "LayerElementUV");
-            leExtra.AddChild("TypedIndex", int32_t(lr));
-            layerExtra.AddChild(leExtra);
-            layerExtra.Dump(outstream, binary, indent);
-        }
-        // finish the node record
-        indent = 1;
-        n.End(outstream, binary, indent, true);
-    }
-
-    // aiMaterial
-    material_uids.clear();
-    for (size_t i = 0; i < mScene->mNumMaterials; ++i) {
-        // it's all about this material
-        aiMaterial* m = mScene->mMaterials[i];
-
-        // these are used to receive material data
-        float f; aiColor3D c;
-
-        // start the node record
-        FBX::Node n("Material");
-
-        int64_t uid = generate_uid();
-        material_uids.push_back(uid);
-        n.AddProperty(uid);
-
-        aiString name;
-        m->Get(AI_MATKEY_NAME, name);
-        n.AddProperty(name.C_Str() + FBX::SEPARATOR + "Material");
-
-        n.AddProperty("");
-
-        n.AddChild("Version", int32_t(102));
-        f = 0;
-        m->Get(AI_MATKEY_SHININESS, f);
-        bool phong = (f > 0);
-        if (phong) {
-            n.AddChild("ShadingModel", "phong");
-        } else {
-            n.AddChild("ShadingModel", "lambert");
-        }
-        n.AddChild("MultiLayer", int32_t(0));
-
-        FBX::Node p("Properties70");
-
-        // materials exported using the FBX SDK have two sets of fields.
-        // there are the properties specified in the PropertyTemplate,
-        // which are those supported by the modernFBX SDK,
-        // and an extra set of properties with simpler names.
-        // The extra properties are a legacy material system from pre-2009.
-        //
-        // In the modern system, each property has "color" and "factor".
-        // Generally the interpretation of these seems to be
-        // that the colour is multiplied by the factor before use,
-        // but this is not always clear-cut.
-        //
-        // Usually assimp only stores the colour,
-        // so we can just leave the factors at the default "1.0".
-
-        // first we can export the "standard" properties
-        if (m->Get(AI_MATKEY_COLOR_AMBIENT, c) == aiReturn_SUCCESS) {
-            p.AddP70colorA("AmbientColor", c.r, c.g, c.b);
-            //p.AddP70numberA("AmbientFactor", 1.0);
-        }
-        if (m->Get(AI_MATKEY_COLOR_DIFFUSE, c) == aiReturn_SUCCESS) {
-            p.AddP70colorA("DiffuseColor", c.r, c.g, c.b);
-            //p.AddP70numberA("DiffuseFactor", 1.0);
-        }
-        if (m->Get(AI_MATKEY_COLOR_TRANSPARENT, c) == aiReturn_SUCCESS) {
-            // "TransparentColor" / "TransparencyFactor"...
-            // thanks FBX, for your insightful interpretation of consistency
-            p.AddP70colorA("TransparentColor", c.r, c.g, c.b);
-            // TransparencyFactor defaults to 0.0, so set it to 1.0.
-            // note: Maya always sets this to 1.0,
-            // so we can't use it sensibly as "Opacity".
-            // In stead we rely on the legacy "Opacity" value, below.
-            // Blender also relies on "Opacity" not "TransparencyFactor",
-            // probably for a similar reason.
-            p.AddP70numberA("TransparencyFactor", 1.0);
-        }
-        if (m->Get(AI_MATKEY_COLOR_REFLECTIVE, c) == aiReturn_SUCCESS) {
-            p.AddP70colorA("ReflectionColor", c.r, c.g, c.b);
-        }
-        if (m->Get(AI_MATKEY_REFLECTIVITY, f) == aiReturn_SUCCESS) {
-            p.AddP70numberA("ReflectionFactor", f);
-        }
-        if (phong) {
-            if (m->Get(AI_MATKEY_COLOR_SPECULAR, c) == aiReturn_SUCCESS) {
-                p.AddP70colorA("SpecularColor", c.r, c.g, c.b);
-            }
-            if (m->Get(AI_MATKEY_SHININESS_STRENGTH, f) == aiReturn_SUCCESS) {
-                p.AddP70numberA("ShininessFactor", f);
-            }
-            if (m->Get(AI_MATKEY_SHININESS, f) == aiReturn_SUCCESS) {
-                p.AddP70numberA("ShininessExponent", f);
-            }
-            if (m->Get(AI_MATKEY_REFLECTIVITY, f) == aiReturn_SUCCESS) {
-                p.AddP70numberA("ReflectionFactor", f);
-            }
-        }
-
-        // Now the legacy system.
-        // For safety let's include it.
-        // thrse values don't exist in the property template,
-        // and usually are completely ignored when loading.
-        // One notable exception is the "Opacity" property,
-        // which Blender uses as (1.0 - alpha).
-        c.r = 0.0f; c.g = 0.0f; c.b = 0.0f;
-        m->Get(AI_MATKEY_COLOR_EMISSIVE, c);
-        p.AddP70vector("Emissive", c.r, c.g, c.b);
-        c.r = 0.2f; c.g = 0.2f; c.b = 0.2f;
-        m->Get(AI_MATKEY_COLOR_AMBIENT, c);
-        p.AddP70vector("Ambient", c.r, c.g, c.b);
-        c.r = 0.8f; c.g = 0.8f; c.b = 0.8f;
-        m->Get(AI_MATKEY_COLOR_DIFFUSE, c);
-        p.AddP70vector("Diffuse", c.r, c.g, c.b);
-        // The FBX SDK determines "Opacity" from transparency colour (RGB)
-        // and factor (F) as: O = (1.0 - F * ((R + G + B) / 3)).
-        // However we actually have an opacity value,
-        // so we should take it from AI_MATKEY_OPACITY if possible.
-        // It might make more sense to use TransparencyFactor,
-        // but Blender actually loads "Opacity" correctly, so let's use it.
-        f = 1.0f;
-        if (m->Get(AI_MATKEY_COLOR_TRANSPARENT, c) == aiReturn_SUCCESS) {
-            f = 1.0f - ((c.r + c.g + c.b) / 3.0f);
-        }
-        m->Get(AI_MATKEY_OPACITY, f);
-        p.AddP70double("Opacity", f);
-        if (phong) {
-            // specular color is multiplied by shininess_strength
-            c.r = 0.2f; c.g = 0.2f; c.b = 0.2f;
-            m->Get(AI_MATKEY_COLOR_SPECULAR, c);
-            f = 1.0f;
-            m->Get(AI_MATKEY_SHININESS_STRENGTH, f);
-            p.AddP70vector("Specular", f*c.r, f*c.g, f*c.b);
-            f = 20.0f;
-            m->Get(AI_MATKEY_SHININESS, f);
-            p.AddP70double("Shininess", f);
-            // Legacy "Reflectivity" is F*F*((R+G+B)/3),
-            // where F is the proportion of light reflected (AKA reflectivity),
-            // and RGB is the reflective colour of the material.
-            // No idea why, but we might as well set it the same way.
-            f = 0.0f;
-            m->Get(AI_MATKEY_REFLECTIVITY, f);
-            c.r = 1.0f, c.g = 1.0f, c.b = 1.0f;
-            m->Get(AI_MATKEY_COLOR_REFLECTIVE, c);
-            p.AddP70double("Reflectivity", f*f*((c.r+c.g+c.b)/3.0));
-        }
-
-        n.AddChild(p);
-
-        n.Dump(outstream, binary, indent);
-    }
-
-    // we need to look up all the images we're using,
-    // so we can generate uids, and eliminate duplicates.
-    std::map<std::string, int64_t> uid_by_image;
-    for (size_t i = 0; i < mScene->mNumMaterials; ++i) {
-        aiString texpath;
-        aiMaterial* mat = mScene->mMaterials[i];
-        for (
-            size_t tt = aiTextureType_DIFFUSE;
-            tt < aiTextureType_UNKNOWN;
-            ++tt
-        ){
-            const aiTextureType textype = static_cast<aiTextureType>(tt);
-            const size_t texcount = mat->GetTextureCount(textype);
-            for (size_t j = 0; j < texcount; ++j) {
-                mat->GetTexture(textype, (unsigned int)j, &texpath);
-                const std::string texstring = texpath.C_Str();
-                auto elem = uid_by_image.find(texstring);
-                if (elem == uid_by_image.end()) {
-                    uid_by_image[texstring] = generate_uid();
-                }
-            }
-        }
-    }
-
-    // FbxVideo - stores images used by textures.
-    for (const auto &it : uid_by_image) {
-        FBX::Node n("Video");
-        const int64_t& uid = it.second;
-        const std::string name = ""; // TODO: ... name???
-        n.AddProperties(uid, name + FBX::SEPARATOR + "Video", "Clip");
-        n.AddChild("Type", "Clip");
-        FBX::Node p("Properties70");
-        // TODO: get full path... relative path... etc... ugh...
-        // for now just use the same path for everything,
-        // and hopefully one of them will work out.
-        std::string path = it.first;
-        // try get embedded texture
-        const aiTexture* embedded_texture = mScene->GetEmbeddedTexture(it.first.c_str());
-        if (embedded_texture != nullptr) {
-            // change the path (use original filename, if available. If name is empty, concatenate texture index with file extension)
-            std::stringstream newPath;
-            if (embedded_texture->mFilename.length > 0) {
-                newPath << embedded_texture->mFilename.C_Str();
-            } else if (embedded_texture->achFormatHint[0]) {
-                int texture_index = std::stoi(path.substr(1, path.size() - 1));
-                newPath << texture_index << "." << embedded_texture->achFormatHint;
-            }
-            path = newPath.str();
-            // embed the texture
-            size_t texture_size = static_cast<size_t>(embedded_texture->mWidth * std::max(embedded_texture->mHeight, 1u));
-            if (binary) {
-                // embed texture as binary data
-                std::vector<uint8_t> tex_data;
-                tex_data.resize(texture_size);
-                memcpy(&tex_data[0], (char*)embedded_texture->pcData, texture_size);
-                n.AddChild("Content", tex_data);
-            } else {
-                // embed texture in base64 encoding
-                std::string encoded_texture = FBX::Util::EncodeBase64((char*)embedded_texture->pcData, texture_size);
-                n.AddChild("Content", encoded_texture);
-            }
-        }
-        p.AddP70("Path", "KString", "XRefUrl", "", path);
-        n.AddChild(p);
-        n.AddChild("UseMipMap", int32_t(0));
-        n.AddChild("Filename", path);
-        n.AddChild("RelativeFilename", path);
-        n.Dump(outstream, binary, indent);
-    }
-
-    // Textures
-    // referenced by material_index/texture_type pairs.
-    std::map<std::pair<size_t,size_t>,int64_t> texture_uids;
-    const std::map<aiTextureType,std::string> prop_name_by_tt = {
-        {aiTextureType_DIFFUSE,      "DiffuseColor"},
-        {aiTextureType_SPECULAR,     "SpecularColor"},
-        {aiTextureType_AMBIENT,      "AmbientColor"},
-        {aiTextureType_EMISSIVE,     "EmissiveColor"},
-        {aiTextureType_HEIGHT,       "Bump"},
-        {aiTextureType_NORMALS,      "NormalMap"},
-        {aiTextureType_SHININESS,    "ShininessExponent"},
-        {aiTextureType_OPACITY,      "TransparentColor"},
-        {aiTextureType_DISPLACEMENT, "DisplacementColor"},
-        //{aiTextureType_LIGHTMAP, "???"},
-        {aiTextureType_REFLECTION,   "ReflectionColor"}
-        //{aiTextureType_UNKNOWN, ""}
-    };
-    for (size_t i = 0; i < mScene->mNumMaterials; ++i) {
-        // textures are attached to materials
-        aiMaterial* mat = mScene->mMaterials[i];
-        int64_t material_uid = material_uids[i];
-
-        for (
-            size_t j = aiTextureType_DIFFUSE;
-            j < aiTextureType_UNKNOWN;
-            ++j
-        ) {
-            const aiTextureType tt = static_cast<aiTextureType>(j);
-            size_t n = mat->GetTextureCount(tt);
-
-            if (n < 1) { // no texture of this type
-                continue;
-            }
-
-            if (n > 1) {
-                // TODO: multilayer textures
-                std::stringstream err;
-                err << "Multilayer textures not supported (for now),";
-                err << " skipping texture type " << j;
-                err << " of material " << i;
-                ASSIMP_LOG_WARN(err.str());
-            }
-
-            // get image path for this (single-image) texture
-            aiString tpath;
-            if (mat->GetTexture(tt, 0, &tpath) != aiReturn_SUCCESS) {
-                std::stringstream err;
-                err << "Failed to get texture 0 for texture of type " << tt;
-                err << " on material " << i;
-                err << ", however GetTextureCount returned 1.";
-                throw DeadlyExportError(err.str());
-            }
-            const std::string texture_path(tpath.C_Str());
-
-            // get connected image uid
-            auto elem = uid_by_image.find(texture_path);
-            if (elem == uid_by_image.end()) {
-                // this should never happen
-                std::stringstream err;
-                err << "Failed to find video element for texture with path";
-                err << " \"" << texture_path << "\"";
-                err << ", type " << j << ", material " << i;
-                throw DeadlyExportError(err.str());
-            }
-            const int64_t image_uid = elem->second;
-
-            // get the name of the material property to connect to
-            auto elem2 = prop_name_by_tt.find(tt);
-            if (elem2 == prop_name_by_tt.end()) {
-                // don't know how to handle this type of texture,
-                // so skip it.
-                std::stringstream err;
-                err << "Not sure how to handle texture of type " << j;
-                err << " on material " << i;
-                err << ", skipping...";
-                ASSIMP_LOG_WARN(err.str());
-                continue;
-            }
-            const std::string& prop_name = elem2->second;
-
-            // generate a uid for this texture
-            const int64_t texture_uid = generate_uid();
-
-            // link the texture to the material
-            connections.emplace_back(
-                "C", "OP", texture_uid, material_uid, prop_name
-            );
-
-            // link the image data to the texture
-            connections.emplace_back("C", "OO", image_uid, texture_uid);
-
-            // now write the actual texture node
-            FBX::Node tnode("Texture");
-            // TODO: some way to determine texture name?
-            const std::string texture_name = "" + FBX::SEPARATOR + "Texture";
-            tnode.AddProperties(texture_uid, texture_name, "");
-            // there really doesn't seem to be a better type than this:
-            tnode.AddChild("Type", "TextureVideoClip");
-            tnode.AddChild("Version", int32_t(202));
-            tnode.AddChild("TextureName", texture_name);
-            FBX::Node p("Properties70");
-            p.AddP70enum("CurrentTextureBlendMode", 0); // TODO: verify
-            //p.AddP70string("UVSet", ""); // TODO: how should this work?
-            p.AddP70bool("UseMaterial", 1);
-            tnode.AddChild(p);
-            // can't easily detrmine which texture path will be correct,
-            // so just store what we have in every field.
-            // these being incorrect is a common problem with FBX anyway.
-            tnode.AddChild("FileName", texture_path);
-            tnode.AddChild("RelativeFilename", texture_path);
-            tnode.AddChild("ModelUVTranslation", double(0.0), double(0.0));
-            tnode.AddChild("ModelUVScaling", double(1.0), double(1.0));
-            tnode.AddChild("Texture_Alpha_Source", "None");
-            tnode.AddChild(
-                "Cropping", int32_t(0), int32_t(0), int32_t(0), int32_t(0)
-            );
-            tnode.Dump(outstream, binary, indent);
-        }
-    }
-
-    // bones.
-    //
-    // output structure:
-    // subset of node hierarchy that are "skeleton",
-    // i.e. do not have meshes but only bones.
-    // but.. i'm not sure how anyone could guarantee that...
-    //
-    // input...
-    // well, for each mesh it has "bones",
-    // and the bone names correspond to nodes.
-    // of course we also need the parent nodes,
-    // as they give some of the transform........
-    //
-    // well. we can assume a sane input, i suppose.
-    //
-    // so input is the bone node hierarchy,
-    // with an extra thing for the transformation of the MESH in BONE space.
-    //
-    // output is a set of bone nodes,
-    // a "bindpose" which indicates the default local transform of all bones,
-    // and a set of "deformers".
-    // each deformer is parented to a mesh geometry,
-    // and has one or more "subdeformer"s as children.
-    // each subdeformer has one bone node as a child,
-    // and represents the influence of that bone on the grandparent mesh.
-    // the subdeformer has a list of indices, and weights,
-    // with indices specifying vertex indices,
-    // and weights specifying the corresponding influence of this bone.
-    // it also has Transform and TransformLink elements,
-    // specifying the transform of the MESH in BONE space,
-    // and the transformation of the BONE in WORLD space,
-    // likely in the bindpose.
-    //
-    // the input bone structure is different but similar,
-    // storing the number of weights for this bone,
-    // and an array of (vertex index, weight) pairs.
-    //
-    // one sticky point is that the number of vertices may not match,
-    // because assimp splits vertices by normal, uv, etc.
-
-    // functor for aiNode sorting
-    struct SortNodeByName
-    {
-        bool operator()(const aiNode *lhs, const aiNode *rhs) const
-        {
-            return strcmp(lhs->mName.C_Str(), rhs->mName.C_Str()) < 0;
-        }
-    };
-
-    // first we should mark the skeleton for each mesh.
-    // the skeleton must include not only the aiBones,
-    // but also all their parent nodes.
-    // anything that affects the position of any bone node must be included.
-    // Use SorNodeByName to make sure the exported result will be the same across all systems
-    // Otherwise the aiNodes of the skeleton would be sorted based on the pointer address, which isn't consistent
-    std::vector<std::set<const aiNode*, SortNodeByName>> skeleton_by_mesh(mScene->mNumMeshes);
-    // at the same time we can build a list of all the skeleton nodes,
-    // which will be used later to mark them as type "limbNode".
-    std::unordered_set<const aiNode*> limbnodes;
-    
-    //actual bone nodes in fbx, without parenting-up
-    std::unordered_set<std::string> setAllBoneNamesInScene;
-    for(unsigned int m = 0; m < mScene->mNumMeshes; ++ m)
-    {
-        aiMesh* pMesh = mScene->mMeshes[m];
-        for(unsigned int b = 0; b < pMesh->mNumBones; ++ b)
-            setAllBoneNamesInScene.insert(pMesh->mBones[b]->mName.data);
-    }
-    aiMatrix4x4 mxTransIdentity;
-    
-    // and a map of nodes by bone name, as finding them is annoying.
-    std::map<std::string,aiNode*> node_by_bone;
-    for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) {
-        const aiMesh* m = mScene->mMeshes[mi];
-        std::set<const aiNode*, SortNodeByName> skeleton;
-        for (size_t bi =0; bi < m->mNumBones; ++bi) {
-            const aiBone* b = m->mBones[bi];
-            const std::string name(b->mName.C_Str());
-            auto elem = node_by_bone.find(name);
-            aiNode* n;
-            if (elem != node_by_bone.end()) {
-                n = elem->second;
-            } else {
-                n = mScene->mRootNode->FindNode(b->mName);
-                if (!n) {
-                    // this should never happen
-                    std::stringstream err;
-                    err << "Failed to find node for bone: \"" << name << "\"";
-                    throw DeadlyExportError(err.str());
-                }
-                node_by_bone[name] = n;
-                limbnodes.insert(n);
-            }
-            skeleton.insert(n);
-            // mark all parent nodes as skeleton as well,
-            // up until we find the root node,
-            // or else the node containing the mesh,
-            // or else the parent of a node containig the mesh.
-            for (
-                const aiNode* parent = n->mParent;
-                parent && parent != mScene->mRootNode;
-                parent = parent->mParent
-            ) {
-                // if we've already done this node we can skip it all
-                if (skeleton.count(parent)) {
-                    break;
-                }
-                // ignore fbx transform nodes as these will be collapsed later
-                // TODO: cache this by aiNode*
-                const std::string node_name(parent->mName.C_Str());
-                if (node_name.find(MAGIC_NODE_TAG) != std::string::npos) {
-                    continue;
-                }
-                //not a bone in scene && no effect in transform
-                if(setAllBoneNamesInScene.find(node_name)==setAllBoneNamesInScene.end()
-                   && parent->mTransformation == mxTransIdentity) {
-                        continue;
-                }
-                // otherwise check if this is the root of the skeleton
-                bool end = false;
-                // is the mesh part of this node?
-                for (size_t i = 0; i < parent->mNumMeshes; ++i) {
-                    if (parent->mMeshes[i] == mi) {
-                        end = true;
-                        break;
-                    }
-                }
-                // is the mesh in one of the children of this node?
-                for (size_t j = 0; j < parent->mNumChildren; ++j) {
-                    aiNode* child = parent->mChildren[j];
-                    for (size_t i = 0; i < child->mNumMeshes; ++i) {
-                        if (child->mMeshes[i] == mi) {
-                            end = true;
-                            break;
-                        }
-                    }
-                    if (end) { break; }
-                }
-                
-                // if it was the skeleton root we can finish here
-                if (end) { break; }
-            }
-        }
-        skeleton_by_mesh[mi] = skeleton;
-    }
-
-    // we'll need the uids for the bone nodes, so generate them now
-    for (size_t i = 0; i < mScene->mNumMeshes; ++i) {
-        auto &s = skeleton_by_mesh[i];
-        for (const aiNode* n : s) {
-            auto elem = node_uids.find(n);
-            if (elem == node_uids.end()) {
-                node_uids[n] = generate_uid();
-            }
-        }
-    }
-
-    // now, for each aiMesh, we need to export a deformer,
-    // and for each aiBone a subdeformer,
-    // which should have all the skinning info.
-    // these will need to be connected properly to the mesh,
-    // and we can do that all now.
-    for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) {
-        const aiMesh* m = mScene->mMeshes[mi];
-        if (!m->HasBones()) {
-            continue;
-        }
-        // make a deformer for this mesh
-        int64_t deformer_uid = generate_uid();
-        FBX::Node dnode("Deformer");
-        dnode.AddProperties(deformer_uid, FBX::SEPARATOR + "Deformer", "Skin");
-        dnode.AddChild("Version", int32_t(101));
-        // "acuracy"... this is not a typo....
-        dnode.AddChild("Link_DeformAcuracy", double(50));
-        dnode.AddChild("SkinningType", "Linear"); // TODO: other modes?
-        dnode.Dump(outstream, binary, indent);
-
-        // connect it
-        connections.emplace_back("C", "OO", deformer_uid, mesh_uids[mi]);
-
-        //computed before
-        std::vector<int32_t>& vertex_indices = vVertexIndice[mi];
-
-        // TODO, FIXME: this won't work if anything is not in the bind pose.
-        // for now if such a situation is detected, we throw an exception.
-        std::set<const aiBone*> not_in_bind_pose;
-        std::set<const aiNode*> no_offset_matrix;
-
-        // first get this mesh's position in world space,
-        // as we'll need it for each subdeformer.
-        //
-        // ...of course taking the position of the MESH doesn't make sense,
-        // as it can be instanced to many nodes.
-        // All we can do is assume no instancing,
-        // and take the first node we find that contains the mesh.
-        aiNode* mesh_node = get_node_for_mesh((unsigned int)mi, mScene->mRootNode);
-        aiMatrix4x4 mesh_xform = get_world_transform(mesh_node, mScene);
-
-        // now make a subdeformer for each bone in the skeleton
-        const std::set<const aiNode*, SortNodeByName> skeleton= skeleton_by_mesh[mi];
-        for (const aiNode* bone_node : skeleton) {
-            // if there's a bone for this node, find it
-            const aiBone* b = nullptr;
-            for (size_t bi = 0; bi < m->mNumBones; ++bi) {
-                // TODO: this probably should index by something else
-                const std::string name(m->mBones[bi]->mName.C_Str());
-                if (node_by_bone[name] == bone_node) {
-                    b = m->mBones[bi];
-                    break;
-                }
-            }
-            if (!b) {
-                no_offset_matrix.insert(bone_node);
-            }
-
-            // start the subdeformer node
-            const int64_t subdeformer_uid = generate_uid();
-            FBX::Node sdnode("Deformer");
-            sdnode.AddProperties(
-                subdeformer_uid, FBX::SEPARATOR + "SubDeformer", "Cluster"
-            );
-            sdnode.AddChild("Version", int32_t(100));
-            sdnode.AddChild("UserData", "", "");
-
-            // add indices and weights, if any
-            if (b) {
-                std::vector<int32_t> subdef_indices;
-                std::vector<double> subdef_weights;
-                int32_t last_index = -1;
-                for (size_t wi = 0; wi < b->mNumWeights; ++wi) {
-                    int32_t vi = vertex_indices[b->mWeights[wi].mVertexId];
-                    if (vi == last_index) {
-                        // only for vertices we exported to fbx
-                        // TODO, FIXME: this assumes identically-located vertices
-                        // will always deform in the same way.
-                        // as assimp doesn't store a separate list of "positions",
-                        // there's not much that can be done about this
-                        // other than assuming that identical position means
-                        // identical vertex.
-                        continue;
-                    }
-                    subdef_indices.push_back(vi);
-                    subdef_weights.push_back(b->mWeights[wi].mWeight);
-                    last_index = vi;
-                }
-                // yes, "indexes"
-                sdnode.AddChild("Indexes", subdef_indices);
-                sdnode.AddChild("Weights", subdef_weights);
-            }
-
-            // transform is the transform of the mesh, but in bone space.
-            // if the skeleton is in the bind pose,
-            // we can take the inverse of the world-space bone transform
-            // and multiply by the world-space transform of the mesh.
-            aiMatrix4x4 bone_xform = get_world_transform(bone_node, mScene);
-            aiMatrix4x4 inverse_bone_xform = bone_xform;
-            inverse_bone_xform.Inverse();
-            aiMatrix4x4 tr = inverse_bone_xform * mesh_xform;
-
-            sdnode.AddChild("Transform", tr);
-
-
-            sdnode.AddChild("TransformLink", bone_xform);
-            // note: this means we ALWAYS rely on the mesh node transform
-            // being unchanged from the time the skeleton was bound.
-            // there's not really any way around this at the moment.
-
-            // done
-            sdnode.Dump(outstream, binary, indent);
-
-            // lastly, connect to the parent deformer
-            connections.emplace_back(
-                "C", "OO", subdeformer_uid, deformer_uid
-            );
-
-            // we also need to connect the limb node to the subdeformer.
-            connections.emplace_back(
-                "C", "OO", node_uids[bone_node], subdeformer_uid
-            );
-        }
-
-        // if we cannot create a valid FBX file, simply die.
-        // this will both prevent unnecessary bug reports,
-        // and tell the user what they can do to fix the situation
-        // (i.e. export their model in the bind pose).
-        if (no_offset_matrix.size() && not_in_bind_pose.size()) {
-            std::stringstream err;
-            err << "Not enough information to construct bind pose";
-            err << " for mesh " << mi << "!";
-            err << " Transform matrix for bone \"";
-            err << (*not_in_bind_pose.begin())->mName.C_Str() << "\"";
-            if (not_in_bind_pose.size() > 1) {
-                err << " (and " << not_in_bind_pose.size() - 1 << " more)";
-            }
-            err << " does not match mOffsetMatrix,";
-            err << " and node \"";
-            err << (*no_offset_matrix.begin())->mName.C_Str() << "\"";
-            if (no_offset_matrix.size() > 1) {
-                err << " (and " << no_offset_matrix.size() - 1 << " more)";
-            }
-            err << " has no offset matrix to rely on.";
-            err << " Please ensure bones are in the bind pose to export.";
-            throw DeadlyExportError(err.str());
-        }
-
-    }
-
-    // BindPose
-    //
-    // This is a legacy system, which should be unnecessary.
-    //
-    // Somehow including it slows file loading by the official FBX SDK,
-    // and as it can reconstruct it from the deformers anyway,
-    // this is not currently included.
-    //
-    // The code is kept here in case it's useful in the future,
-    // but it's pretty much a hack anyway,
-    // as assimp doesn't store bindpose information for full skeletons.
-    //
-    /*for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) {
-        aiMesh* mesh = mScene->mMeshes[mi];
-        if (! mesh->HasBones()) { continue; }
-        int64_t bindpose_uid = generate_uid();
-        FBX::Node bpnode("Pose");
-        bpnode.AddProperty(bindpose_uid);
-        // note: this uid is never linked or connected to anything.
-        bpnode.AddProperty(FBX::SEPARATOR + "Pose"); // blank name
-        bpnode.AddProperty("BindPose");
-
-        bpnode.AddChild("Type", "BindPose");
-        bpnode.AddChild("Version", int32_t(100));
-
-        aiNode* mesh_node = get_node_for_mesh(mi, mScene->mRootNode);
-
-        // next get the whole skeleton for this mesh.
-        // we need it all to define the bindpose section.
-        // the FBX SDK will complain if it's missing,
-        // and also if parents of used bones don't have a subdeformer.
-        // order shouldn't matter.
-        std::set<aiNode*> skeleton;
-        for (size_t bi = 0; bi < mesh->mNumBones; ++bi) {
-            // bone node should have already been indexed
-            const aiBone* b = mesh->mBones[bi];
-            const std::string bone_name(b->mName.C_Str());
-            aiNode* parent = node_by_bone[bone_name];
-            // insert all nodes down to the root or mesh node
-            while (
-                parent
-                && parent != mScene->mRootNode
-                && parent != mesh_node
-            ) {
-                skeleton.insert(parent);
-                parent = parent->mParent;
-            }
-        }
-
-        // number of pose nodes. includes one for the mesh itself.
-        bpnode.AddChild("NbPoseNodes", int32_t(1 + skeleton.size()));
-
-        // the first pose node is always the mesh itself
-        FBX::Node pose("PoseNode");
-        pose.AddChild("Node", mesh_uids[mi]);
-        aiMatrix4x4 mesh_node_xform = get_world_transform(mesh_node, mScene);
-        pose.AddChild("Matrix", mesh_node_xform);
-        bpnode.AddChild(pose);
-
-        for (aiNode* bonenode : skeleton) {
-            // does this node have a uid yet?
-            int64_t node_uid;
-            auto node_uid_iter = node_uids.find(bonenode);
-            if (node_uid_iter != node_uids.end()) {
-                node_uid = node_uid_iter->second;
-            } else {
-                node_uid = generate_uid();
-                node_uids[bonenode] = node_uid;
-            }
-
-            // make a pose thingy
-            pose = FBX::Node("PoseNode");
-            pose.AddChild("Node", node_uid);
-            aiMatrix4x4 node_xform = get_world_transform(bonenode, mScene);
-            pose.AddChild("Matrix", node_xform);
-            bpnode.AddChild(pose);
-        }
-
-        // now write it
-        bpnode.Dump(outstream, binary, indent);
-    }*/
-
-    // TODO: cameras, lights
-
-    // write nodes (i.e. model hierarchy)
-    // start at root node
-    WriteModelNodes(
-        outstream, mScene->mRootNode, 0, limbnodes
-    );
-
-    // animations
-    //
-    // in FBX there are:
-    // * AnimationStack - corresponds to an aiAnimation
-    // * AnimationLayer - a combinable animation component
-    // * AnimationCurveNode - links the property to be animated
-    // * AnimationCurve - defines animation data for a single property value
-    //
-    // the CurveNode also provides the default value for a property,
-    // such as the X, Y, Z coordinates for animatable translation.
-    //
-    // the Curve only specifies values for one component of the property,
-    // so there will be a separate AnimationCurve for X, Y, and Z.
-    //
-    // Assimp has:
-    // * aiAnimation - basically corresponds to an AnimationStack
-    // * aiNodeAnim - defines all animation for one aiNode
-    // * aiVectorKey/aiQuatKey - define the keyframe data for T/R/S
-    //
-    // assimp has no equivalent for AnimationLayer,
-    // and these are flattened on FBX import.
-    // we can assume there will be one per AnimationStack.
-    //
-    // the aiNodeAnim contains all animation data for a single aiNode,
-    // which will correspond to three AnimationCurveNode's:
-    // one each for translation, rotation and scale.
-    // The data for each of these will be put in 9 AnimationCurve's,
-    // T.X, T.Y, T.Z, R.X, R.Y, R.Z, etc.
-
-    // AnimationStack / aiAnimation
-    std::vector<int64_t> animation_stack_uids(mScene->mNumAnimations);
-    for (size_t ai = 0; ai < mScene->mNumAnimations; ++ai) {
-        int64_t animstack_uid = generate_uid();
-        animation_stack_uids[ai] = animstack_uid;
-        const aiAnimation* anim = mScene->mAnimations[ai];
-
-        FBX::Node asnode("AnimationStack");
-        std::string name = anim->mName.C_Str() + FBX::SEPARATOR + "AnimStack";
-        asnode.AddProperties(animstack_uid, name, "");
-        FBX::Node p("Properties70");
-        p.AddP70time("LocalStart", 0); // assimp doesn't store this
-        p.AddP70time("LocalStop", to_ktime(anim->mDuration, anim));
-        p.AddP70time("ReferenceStart", 0);
-        p.AddP70time("ReferenceStop", to_ktime(anim->mDuration, anim));
-        asnode.AddChild(p);
-
-        // this node absurdly always pretends it has children
-        // (in this case it does, but just in case...)
-        asnode.force_has_children = true;
-        asnode.Dump(outstream, binary, indent);
-
-        // note: animation stacks are not connected to anything
-    }
-
-    // AnimationLayer - one per aiAnimation
-    std::vector<int64_t> animation_layer_uids(mScene->mNumAnimations);
-    for (size_t ai = 0; ai < mScene->mNumAnimations; ++ai) {
-        int64_t animlayer_uid = generate_uid();
-        animation_layer_uids[ai] = animlayer_uid;
-        FBX::Node alnode("AnimationLayer");
-        alnode.AddProperties(animlayer_uid, FBX::SEPARATOR + "AnimLayer", "");
-
-        // this node absurdly always pretends it has children
-        alnode.force_has_children = true;
-        alnode.Dump(outstream, binary, indent);
-
-        // connect to the relevant animstack
-        connections.emplace_back(
-            "C", "OO", animlayer_uid, animation_stack_uids[ai]
-        );
-    }
-
-    // AnimCurveNode - three per aiNodeAnim
-    std::vector<std::vector<std::array<int64_t,3>>> curve_node_uids;
-    for (size_t ai = 0; ai < mScene->mNumAnimations; ++ai) {
-        const aiAnimation* anim = mScene->mAnimations[ai];
-        const int64_t layer_uid = animation_layer_uids[ai];
-        std::vector<std::array<int64_t,3>> nodeanim_uids;
-        for (size_t nai = 0; nai < anim->mNumChannels; ++nai) {
-            const aiNodeAnim* na = anim->mChannels[nai];
-            // get the corresponding aiNode
-            const aiNode* node = mScene->mRootNode->FindNode(na->mNodeName);
-            // and its transform
-            const aiMatrix4x4 node_xfm = get_world_transform(node, mScene);
-            aiVector3D T, R, S;
-            node_xfm.Decompose(S, R, T);
-
-            // AnimationCurveNode uids
-            std::array<int64_t,3> ids;
-            ids[0] = generate_uid(); // T
-            ids[1] = generate_uid(); // R
-            ids[2] = generate_uid(); // S
-
-            // translation
-            WriteAnimationCurveNode(outstream,
-                ids[0], "T", T, "Lcl Translation",
-                layer_uid, node_uids[node]
-            );
-
-            // rotation
-            WriteAnimationCurveNode(outstream,
-                ids[1], "R", R, "Lcl Rotation",
-                layer_uid, node_uids[node]
-            );
-
-            // scale
-            WriteAnimationCurveNode(outstream,
-                ids[2], "S", S, "Lcl Scale",
-                layer_uid, node_uids[node]
-            );
-
-            // store the uids for later use
-            nodeanim_uids.push_back(ids);
-        }
-        curve_node_uids.push_back(nodeanim_uids);
-    }
-
-    // AnimCurve - defines actual keyframe data.
-    // there's a separate curve for every component of every vector,
-    // for example a transform curvenode will have separate X/Y/Z AnimCurve's
-    for (size_t ai = 0; ai < mScene->mNumAnimations; ++ai) {
-        const aiAnimation* anim = mScene->mAnimations[ai];
-        for (size_t nai = 0; nai < anim->mNumChannels; ++nai) {
-            const aiNodeAnim* na = anim->mChannels[nai];
-            // get the corresponding aiNode
-            const aiNode* node = mScene->mRootNode->FindNode(na->mNodeName);
-            // and its transform
-            const aiMatrix4x4 node_xfm = get_world_transform(node, mScene);
-            aiVector3D T, R, S;
-            node_xfm.Decompose(S, R, T);
-            const std::array<int64_t,3>& ids = curve_node_uids[ai][nai];
-
-            std::vector<int64_t> times;
-            std::vector<float> xval, yval, zval;
-
-            // position/translation
-            for (size_t ki = 0; ki < na->mNumPositionKeys; ++ki) {
-                const aiVectorKey& k = na->mPositionKeys[ki];
-                times.push_back(to_ktime(k.mTime));
-                xval.push_back(k.mValue.x);
-                yval.push_back(k.mValue.y);
-                zval.push_back(k.mValue.z);
-            }
-            // one curve each for X, Y, Z
-            WriteAnimationCurve(outstream, T.x, times, xval, ids[0], "d|X");
-            WriteAnimationCurve(outstream, T.y, times, yval, ids[0], "d|Y");
-            WriteAnimationCurve(outstream, T.z, times, zval, ids[0], "d|Z");
-
-            // rotation
-            times.clear(); xval.clear(); yval.clear(); zval.clear();
-            for (size_t ki = 0; ki < na->mNumRotationKeys; ++ki) {
-                const aiQuatKey& k = na->mRotationKeys[ki];
-                times.push_back(to_ktime(k.mTime));
-                // TODO: aiQuaternion method to convert to Euler...
-                aiMatrix4x4 m(k.mValue.GetMatrix());
-                aiVector3D qs, qr, qt;
-                m.Decompose(qs, qr, qt);
-                qr *= DEG;
-                xval.push_back(qr.x);
-                yval.push_back(qr.y);
-                zval.push_back(qr.z);
-            }
-            WriteAnimationCurve(outstream, R.x, times, xval, ids[1], "d|X");
-            WriteAnimationCurve(outstream, R.y, times, yval, ids[1], "d|Y");
-            WriteAnimationCurve(outstream, R.z, times, zval, ids[1], "d|Z");
-
-            // scaling/scale
-            times.clear(); xval.clear(); yval.clear(); zval.clear();
-            for (size_t ki = 0; ki < na->mNumScalingKeys; ++ki) {
-                const aiVectorKey& k = na->mScalingKeys[ki];
-                times.push_back(to_ktime(k.mTime));
-                xval.push_back(k.mValue.x);
-                yval.push_back(k.mValue.y);
-                zval.push_back(k.mValue.z);
-            }
-            WriteAnimationCurve(outstream, S.x, times, xval, ids[2], "d|X");
-            WriteAnimationCurve(outstream, S.y, times, yval, ids[2], "d|Y");
-            WriteAnimationCurve(outstream, S.z, times, zval, ids[2], "d|Z");
-        }
-    }
-
-    indent = 0;
-    object_node.End(outstream, binary, indent, true);
-}
-
-// convenience map of magic node name strings to FBX properties,
-// including the expected type of transform.
-const std::map<std::string,std::pair<std::string,char>> transform_types = {
-    {"Translation", {"Lcl Translation", 't'}},
-    {"RotationOffset", {"RotationOffset", 't'}},
-    {"RotationPivot", {"RotationPivot", 't'}},
-    {"PreRotation", {"PreRotation", 'r'}},
-    {"Rotation", {"Lcl Rotation", 'r'}},
-    {"PostRotation", {"PostRotation", 'r'}},
-    {"RotationPivotInverse", {"RotationPivotInverse", 'i'}},
-    {"ScalingOffset", {"ScalingOffset", 't'}},
-    {"ScalingPivot", {"ScalingPivot", 't'}},
-    {"Scaling", {"Lcl Scaling", 's'}},
-    {"ScalingPivotInverse", {"ScalingPivotInverse", 'i'}},
-    {"GeometricScaling", {"GeometricScaling", 's'}},
-    {"GeometricRotation", {"GeometricRotation", 'r'}},
-    {"GeometricTranslation", {"GeometricTranslation", 't'}},
-    {"GeometricTranslationInverse", {"GeometricTranslationInverse", 'i'}},
-    {"GeometricRotationInverse", {"GeometricRotationInverse", 'i'}},
-    {"GeometricScalingInverse", {"GeometricScalingInverse", 'i'}}
-};
-
-// write a single model node to the stream
-void FBXExporter::WriteModelNode(
-    StreamWriterLE& outstream,
-    bool binary,
-    const aiNode* node,
-    int64_t node_uid,
-    const std::string& type,
-    const std::vector<std::pair<std::string,aiVector3D>>& transform_chain,
-    TransformInheritance inherit_type
-){
-    const aiVector3D zero = {0, 0, 0};
-    const aiVector3D one = {1, 1, 1};
-    FBX::Node m("Model");
-    std::string name = node->mName.C_Str() + FBX::SEPARATOR + "Model";
-    m.AddProperties(node_uid, name, type);
-    m.AddChild("Version", int32_t(232));
-    FBX::Node p("Properties70");
-    p.AddP70bool("RotationActive", 1);
-    p.AddP70int("DefaultAttributeIndex", 0);
-    p.AddP70enum("InheritType", inherit_type);
-    if (transform_chain.empty()) {
-        // decompose 4x4 transform matrix into TRS
-        aiVector3D t, r, s;
-        node->mTransformation.Decompose(s, r, t);
-        if (t != zero) {
-            p.AddP70(
-                "Lcl Translation", "Lcl Translation", "", "A",
-                double(t.x), double(t.y), double(t.z)
-            );
-        }
-        if (r != zero) {
-            p.AddP70(
-                "Lcl Rotation", "Lcl Rotation", "", "A",
-                double(DEG*r.x), double(DEG*r.y), double(DEG*r.z)
-            );
-        }
-        if (s != one) {
-            p.AddP70(
-                "Lcl Scaling", "Lcl Scaling", "", "A",
-                double(s.x), double(s.y), double(s.z)
-            );
-        }
-    } else {
-        // apply the transformation chain.
-        // these transformation elements are created when importing FBX,
-        // which has a complex transformation hierarchy for each node.
-        // as such we can bake the hierarchy back into the node on export.
-        for (auto &item : transform_chain) {
-            auto elem = transform_types.find(item.first);
-            if (elem == transform_types.end()) {
-                // then this is a bug
-                std::stringstream err;
-                err << "unrecognized FBX transformation type: ";
-                err << item.first;
-                throw DeadlyExportError(err.str());
-            }
-            const std::string &name = elem->second.first;
-            const aiVector3D &v = item.second;
-            if (name.compare(0, 4, "Lcl ") == 0) {
-                // special handling for animatable properties
-                p.AddP70(
-                    name, name, "", "A",
-                    double(v.x), double(v.y), double(v.z)
-                );
-            } else {
-                p.AddP70vector(name, v.x, v.y, v.z);
-            }
-        }
-    }
-    m.AddChild(p);
-
-    // not sure what these are for,
-    // but they seem to be omnipresent
-    m.AddChild("Shading", FBXExportProperty(true));
-    m.AddChild("Culling", FBXExportProperty("CullingOff"));
-
-    m.Dump(outstream, binary, 1);
-}
-
-// wrapper for WriteModelNodes to create and pass a blank transform chain
-void FBXExporter::WriteModelNodes(
-    StreamWriterLE& s,
-    const aiNode* node,
-    int64_t parent_uid,
-    const std::unordered_set<const aiNode*>& limbnodes
-) {
-    std::vector<std::pair<std::string,aiVector3D>> chain;
-    WriteModelNodes(s, node, parent_uid, limbnodes, chain);
-}
-
-void FBXExporter::WriteModelNodes(
-    StreamWriterLE& outstream,
-    const aiNode* node,
-    int64_t parent_uid,
-    const std::unordered_set<const aiNode*>& limbnodes,
-    std::vector<std::pair<std::string,aiVector3D>>& transform_chain
-) {
-    // first collapse any expanded transformation chains created by FBX import.
-    std::string node_name(node->mName.C_Str());
-    if (node_name.find(MAGIC_NODE_TAG) != std::string::npos) {
-        auto pos = node_name.find(MAGIC_NODE_TAG) + MAGIC_NODE_TAG.size() + 1;
-        std::string type_name = node_name.substr(pos);
-        auto elem = transform_types.find(type_name);
-        if (elem == transform_types.end()) {
-            // then this is a bug and should be fixed
-            std::stringstream err;
-            err << "unrecognized FBX transformation node";
-            err << " of type " << type_name << " in node " << node_name;
-            throw DeadlyExportError(err.str());
-        }
-        aiVector3D t, r, s;
-        node->mTransformation.Decompose(s, r, t);
-        switch (elem->second.second) {
-        case 'i': // inverse
-            // we don't need to worry about the inverse matrices
-            break;
-        case 't': // translation
-            transform_chain.emplace_back(elem->first, t);
-            break;
-        case 'r': // rotation
-            r *= float(DEG);
-            transform_chain.emplace_back(elem->first, r);
-            break;
-        case 's': // scale
-            transform_chain.emplace_back(elem->first, s);
-            break;
-        default:
-            // this should never happen
-            std::stringstream err;
-            err << "unrecognized FBX transformation type code: ";
-            err << elem->second.second;
-            throw DeadlyExportError(err.str());
-        }
-        // now continue on to any child nodes
-        for (unsigned i = 0; i < node->mNumChildren; ++i) {
-            WriteModelNodes(
-                outstream,
-                node->mChildren[i],
-                parent_uid,
-                limbnodes,
-                transform_chain
-            );
-        }
-        return;
-    }
-
-    int64_t node_uid = 0;
-    // generate uid and connect to parent, if not the root node,
-    if (node != mScene->mRootNode) {
-        auto elem = node_uids.find(node);
-        if (elem != node_uids.end()) {
-            node_uid = elem->second;
-        } else {
-            node_uid = generate_uid();
-            node_uids[node] = node_uid;
-        }
-        connections.emplace_back("C", "OO", node_uid, parent_uid);
-    }
-
-    // what type of node is this?
-    if (node == mScene->mRootNode) {
-        // handled later
-    } else if (node->mNumMeshes == 1) {
-        // connect to child mesh, which should have been written previously
-        connections.emplace_back(
-            "C", "OO", mesh_uids[node->mMeshes[0]], node_uid
-        );
-        // also connect to the material for the child mesh
-        connections.emplace_back(
-            "C", "OO",
-            material_uids[mScene->mMeshes[node->mMeshes[0]]->mMaterialIndex],
-            node_uid
-        );
-        // write model node
-        WriteModelNode(
-            outstream, binary, node, node_uid, "Mesh", transform_chain
-        );
-    } else if (limbnodes.count(node)) {
-        WriteModelNode(
-            outstream, binary, node, node_uid, "LimbNode", transform_chain
-        );
-        // we also need to write a nodeattribute to mark it as a skeleton
-        int64_t node_attribute_uid = generate_uid();
-        FBX::Node na("NodeAttribute");
-        na.AddProperties(
-            node_attribute_uid, FBX::SEPARATOR + "NodeAttribute", "LimbNode"
-        );
-        na.AddChild("TypeFlags", FBXExportProperty("Skeleton"));
-        na.Dump(outstream, binary, 1);
-        // and connect them
-        connections.emplace_back("C", "OO", node_attribute_uid, node_uid);
-    } else {
-        // generate a null node so we can add children to it
-        WriteModelNode(
-            outstream, binary, node, node_uid, "Null", transform_chain
-        );
-    }
-
-    // if more than one child mesh, make nodes for each mesh
-    if (node->mNumMeshes > 1 || node == mScene->mRootNode) {
-        for (size_t i = 0; i < node->mNumMeshes; ++i) {
-            // make a new model node
-            int64_t new_node_uid = generate_uid();
-            // connect to parent node
-            connections.emplace_back("C", "OO", new_node_uid, node_uid);
-            // connect to child mesh, which should have been written previously
-            connections.emplace_back(
-                "C", "OO", mesh_uids[node->mMeshes[i]], new_node_uid
-            );
-            // also connect to the material for the child mesh
-            connections.emplace_back(
-                "C", "OO",
-                material_uids[
-                    mScene->mMeshes[node->mMeshes[i]]->mMaterialIndex
-                ],
-                new_node_uid
-            );
-            // write model node
-            FBX::Node m("Model");
-            // take name from mesh name, if it exists
-            std::string name = mScene->mMeshes[node->mMeshes[i]]->mName.C_Str();
-            name += FBX::SEPARATOR + "Model";
-            m.AddProperties(new_node_uid, name, "Mesh");
-            m.AddChild("Version", int32_t(232));
-            FBX::Node p("Properties70");
-            p.AddP70enum("InheritType", 1);
-            m.AddChild(p);
-            m.Dump(outstream, binary, 1);
-        }
-    }
-
-    // now recurse into children
-    for (size_t i = 0; i < node->mNumChildren; ++i) {
-        WriteModelNodes(
-            outstream, node->mChildren[i], node_uid, limbnodes
-        );
-    }
-}
-
-
-void FBXExporter::WriteAnimationCurveNode(
-    StreamWriterLE& outstream,
-    int64_t uid,
-    const std::string& name, // "T", "R", or "S"
-    aiVector3D default_value,
-    std::string property_name, // "Lcl Translation" etc
-    int64_t layer_uid,
-    int64_t node_uid
-) {
-    FBX::Node n("AnimationCurveNode");
-    n.AddProperties(uid, name + FBX::SEPARATOR + "AnimCurveNode", "");
-    FBX::Node p("Properties70");
-    p.AddP70numberA("d|X", default_value.x);
-    p.AddP70numberA("d|Y", default_value.y);
-    p.AddP70numberA("d|Z", default_value.z);
-    n.AddChild(p);
-    n.Dump(outstream, binary, 1);
-    // connect to layer
-    this->connections.emplace_back("C", "OO", uid, layer_uid);
-    // connect to bone
-    this->connections.emplace_back("C", "OP", uid, node_uid, property_name);
-}
-
-
-void FBXExporter::WriteAnimationCurve(
-    StreamWriterLE& outstream,
-    double default_value,
-    const std::vector<int64_t>& times,
-    const std::vector<float>& values,
-    int64_t curvenode_uid,
-    const std::string& property_link // "d|X", "d|Y", etc
-) {
-    FBX::Node n("AnimationCurve");
-    int64_t curve_uid = generate_uid();
-    n.AddProperties(curve_uid, FBX::SEPARATOR + "AnimCurve", "");
-    n.AddChild("Default", default_value);
-    n.AddChild("KeyVer", int32_t(4009));
-    n.AddChild("KeyTime", times);
-    n.AddChild("KeyValueFloat", values);
-    // TODO: keyattr flags and data (STUB for now)
-    n.AddChild("KeyAttrFlags", std::vector<int32_t>{0});
-    n.AddChild("KeyAttrDataFloat", std::vector<float>{0,0,0,0});
-    n.AddChild(
-        "KeyAttrRefCount",
-        std::vector<int32_t>{static_cast<int32_t>(times.size())}
-    );
-    n.Dump(outstream, binary, 1);
-    this->connections.emplace_back(
-        "C", "OP", curve_uid, curvenode_uid, property_link
-    );
-}
-
-
-void FBXExporter::WriteConnections ()
-{
-    // we should have completed the connection graph already,
-    // so basically just dump it here
-    if (!binary) {
-        WriteAsciiSectionHeader("Object connections");
-    }
-    // TODO: comments with names in the ascii version
-    FBX::Node conn("Connections");
-    StreamWriterLE outstream(outfile);
-    conn.Begin(outstream, binary, 0);
-    conn.BeginChildren(outstream, binary, 0);
-    for (auto &n : connections) {
-        n.Dump(outstream, binary, 1);
-    }
-    conn.End(outstream, binary, 0, !connections.empty());
-    connections.clear();
-}
-
-#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
-#endif // ASSIMP_BUILD_NO_EXPORT

+ 0 - 178
thirdparty/assimp/code/FBX/FBXExporter.h

@@ -1,178 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-copyright notice, this list of conditions and the
-following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the
-following disclaimer in the documentation and/or other
-materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-contributors may be used to endorse or promote products
-derived from this software without specific prior
-written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file FBXExporter.h
-* Declares the exporter class to write a scene to an fbx file
-*/
-#ifndef AI_FBXEXPORTER_H_INC
-#define AI_FBXEXPORTER_H_INC
-
-#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
-
-#include "FBXExportNode.h" // FBX::Node
-#include "FBXCommon.h" // FBX::TransformInheritance
-
-#include <assimp/types.h>
-//#include <assimp/material.h>
-#include <assimp/StreamWriter.h> // StreamWriterLE
-#include <assimp/Exceptional.h> // DeadlyExportError
-
-#include <vector>
-#include <map>
-#include <unordered_set>
-#include <memory> // shared_ptr
-#include <sstream> // stringstream
-
-struct aiScene;
-struct aiNode;
-//struct aiMaterial;
-
-namespace Assimp
-{
-    class IOSystem;
-    class IOStream;
-    class ExportProperties;
-
-    // ---------------------------------------------------------------------
-    /** Helper class to export a given scene to an FBX file. */
-    // ---------------------------------------------------------------------
-    class FBXExporter
-    {
-    public:
-        /// Constructor for a specific scene to export
-        FBXExporter(const aiScene* pScene, const ExportProperties* pProperties);
-
-        // call one of these methods to export
-        void ExportBinary(const char* pFile, IOSystem* pIOSystem);
-        void ExportAscii(const char* pFile, IOSystem* pIOSystem);
-
-    private:
-        bool binary; // whether current export is in binary or ascii format
-        const aiScene* mScene; // the scene to export
-        const ExportProperties* mProperties; // currently unused
-        std::shared_ptr<IOStream> outfile; // file to write to
-
-        std::vector<FBX::Node> connections; // connection storage
-
-        std::vector<int64_t> mesh_uids;
-        std::vector<int64_t> material_uids;
-        std::map<const aiNode*,int64_t> node_uids;
-
-        // this crude unique-ID system is actually fine
-        int64_t last_uid = 999999;
-        int64_t generate_uid() { return ++last_uid; }
-
-        // binary files have a specific header and footer,
-        // in addition to the actual data
-        void WriteBinaryHeader();
-        void WriteBinaryFooter();
-
-        // ascii files have a comment at the top
-        void WriteAsciiHeader();
-
-        // WriteAllNodes does the actual export.
-        // It just calls all the Write<Section> methods below in order.
-        void WriteAllNodes();
-
-        // Methods to write individual sections.
-        // The order here matches the order inside an FBX file.
-        // Each method corresponds to a top-level FBX section,
-        // except WriteHeader which also includes some binary-only sections
-        // and WriteFooter which is binary data only.
-        void WriteHeaderExtension();
-        // WriteFileId(); // binary-only, included in WriteHeader
-        // WriteCreationTime(); // binary-only, included in WriteHeader
-        // WriteCreator(); // binary-only, included in WriteHeader
-        void WriteGlobalSettings();
-        void WriteDocuments();
-        void WriteReferences();
-        void WriteDefinitions();
-        void WriteObjects();
-        void WriteConnections();
-        // WriteTakes(); // deprecated since at least 2015 (fbx 7.4)
-
-        // helpers
-        void WriteAsciiSectionHeader(const std::string& title);
-        void WriteModelNodes(
-            Assimp::StreamWriterLE& s,
-            const aiNode* node,
-            int64_t parent_uid,
-            const std::unordered_set<const aiNode*>& limbnodes
-        );
-        void WriteModelNodes( // usually don't call this directly
-            StreamWriterLE& s,
-            const aiNode* node,
-            int64_t parent_uid,
-            const std::unordered_set<const aiNode*>& limbnodes,
-            std::vector<std::pair<std::string,aiVector3D>>& transform_chain
-        );
-        void WriteModelNode( // nor this
-            StreamWriterLE& s,
-            bool binary,
-            const aiNode* node,
-            int64_t node_uid,
-            const std::string& type,
-            const std::vector<std::pair<std::string,aiVector3D>>& xfm_chain,
-            FBX::TransformInheritance ti_type=FBX::TransformInheritance_RSrs
-        );
-        void WriteAnimationCurveNode(
-            StreamWriterLE& outstream,
-            int64_t uid,
-            const std::string& name, // "T", "R", or "S"
-            aiVector3D default_value,
-            std::string property_name, // "Lcl Translation" etc
-            int64_t animation_layer_uid,
-            int64_t node_uid
-        );
-        void WriteAnimationCurve(
-            StreamWriterLE& outstream,
-            double default_value,
-            const std::vector<int64_t>& times,
-            const std::vector<float>& values,
-            int64_t curvenode_id,
-            const std::string& property_link // "d|X", "d|Y", etc
-        );
-    };
-}
-
-#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
-
-#endif // AI_FBXEXPORTER_H_INC

+ 0 - 164
thirdparty/assimp/code/FBX/FBXImportSettings.h

@@ -1,164 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file  FBXImportSettings.h
- *  @brief FBX importer runtime configuration
- */
-#ifndef INCLUDED_AI_FBX_IMPORTSETTINGS_H
-#define INCLUDED_AI_FBX_IMPORTSETTINGS_H
-
-namespace Assimp {
-namespace FBX {
-
-/** FBX import settings, parts of which are publicly accessible via their corresponding AI_CONFIG constants */
-struct ImportSettings
-{
-    ImportSettings()
-    : strictMode(true)
-    , readAllLayers(true)
-    , readAllMaterials(false)
-    , readMaterials(true)
-    , readTextures(true)
-    , readCameras(true)
-    , readLights(true)
-    , readAnimations(true)
-    , readWeights(true)
-    , preservePivots(true)
-    , optimizeEmptyAnimationCurves(true)
-    , useLegacyEmbeddedTextureNaming(false)
-    , removeEmptyBones( true )
-    , convertToMeters( false ) {
-        // empty
-    }
-
-
-    /** enable strict mode:
-     *   - only accept fbx 2012, 2013 files
-     *   - on the slightest error, give up.
-     *
-     *  Basically, strict mode means that the fbx file will actually
-     *  be validated. Strict mode is off by default. */
-    bool strictMode;
-
-    /** specifies whether all geometry layers are read and scanned for
-      * usable data channels. The FBX spec indicates that many readers
-      * will only read the first channel and that this is in some way
-      * the recommended way- in reality, however, it happens a lot that
-      * vertex data is spread among multiple layers. The default
-      * value for this option is true.*/
-    bool readAllLayers;
-
-    /** specifies whether all materials are read, or only those that
-     *  are referenced by at least one mesh. Reading all materials
-     *  may make FBX reading a lot slower since all objects
-     *  need to be processed .
-     *  This bit is ignored unless readMaterials=true*/
-    bool readAllMaterials;
-
-
-    /** import materials (true) or skip them and assign a default
-     *  material. The default value is true.*/
-    bool readMaterials;
-
-    /** import embedded textures? Default value is true.*/
-    bool readTextures;
-
-    /** import cameras? Default value is true.*/
-    bool readCameras;
-
-    /** import light sources? Default value is true.*/
-    bool readLights;
-
-    /** import animations (i.e. animation curves, the node
-     *  skeleton is always imported). Default value is true. */
-    bool readAnimations;
-
-    /** read bones (vertex weights and deform info).
-     *  Default value is true. */
-    bool readWeights;
-
-    /** preserve transformation pivots and offsets. Since these can
-     *  not directly be represented in assimp, additional dummy
-     *  nodes will be generated. Note that settings this to false
-     *  can make animation import a lot slower. The default value
-     *  is true.
-     *
-     *  The naming scheme for the generated nodes is:
-     *    <OriginalName>_$AssimpFbx$_<TransformName>
-     *
-     *  where <TransformName> is one of
-     *    RotationPivot
-     *    RotationOffset
-     *    PreRotation
-     *    PostRotation
-     *    ScalingPivot
-     *    ScalingOffset
-     *    Translation
-     *    Scaling
-     *    Rotation
-     **/
-    bool preservePivots;
-
-    /** do not import animation curves that specify a constant
-     *  values matching the corresponding node transformation.
-     *  The default value is true. */
-    bool optimizeEmptyAnimationCurves;
-
-    /** use legacy naming for embedded textures eg: (*0, *1, *2)
-    */
-    bool useLegacyEmbeddedTextureNaming;
-
-    /** Empty bones shall be removed
-    */
-    bool removeEmptyBones;
-
-    /** Set to true to perform a conversion from cm to meter after the import
-    */
-    bool convertToMeters;
-};
-
-
-} // !FBX
-} // !Assimp
-
-#endif
-

+ 0 - 198
thirdparty/assimp/code/FBX/FBXImporter.cpp

@@ -1,198 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, 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.
-r
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file  FBXImporter.cpp
- *  @brief Implementation of the FBX importer.
- */
-
-#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
-
-#include "FBXImporter.h"
-
-#include "FBXConverter.h"
-#include "FBXDocument.h"
-#include "FBXParser.h"
-#include "FBXTokenizer.h"
-#include "FBXUtil.h"
-
-#include <assimp/MemoryIOWrapper.h>
-#include <assimp/StreamReader.h>
-#include <assimp/importerdesc.h>
-#include <assimp/Importer.hpp>
-
-namespace Assimp {
-
-template <>
-const char *LogFunctions<FBXImporter>::Prefix() {
-	static auto prefix = "FBX: ";
-	return prefix;
-}
-
-} // namespace Assimp
-
-using namespace Assimp;
-using namespace Assimp::Formatter;
-using namespace Assimp::FBX;
-
-namespace {
-
-static const aiImporterDesc desc = {
-	"Autodesk FBX Importer",
-	"",
-	"",
-	"",
-	aiImporterFlags_SupportTextFlavour,
-	0,
-	0,
-	0,
-	0,
-	"fbx"
-};
-}
-
-// ------------------------------------------------------------------------------------------------
-// Constructor to be privately used by #Importer
-FBXImporter::FBXImporter() {
-}
-
-// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
-FBXImporter::~FBXImporter() {
-}
-
-// ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
-bool FBXImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
-	const std::string &extension = GetExtension(pFile);
-	if (extension == std::string(desc.mFileExtensions)) {
-		return true;
-	}
-
-	else if ((!extension.length() || checkSig) && pIOHandler) {
-		// at least ASCII-FBX files usually have a 'FBX' somewhere in their head
-		const char *tokens[] = { "fbx" };
-		return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
-	}
-	return false;
-}
-
-// ------------------------------------------------------------------------------------------------
-// List all extensions handled by this loader
-const aiImporterDesc *FBXImporter::GetInfo() const {
-	return &desc;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Setup configuration properties for the loader
-void FBXImporter::SetupProperties(const Importer *pImp) {
-	settings.readAllLayers = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_GEOMETRY_LAYERS, true);
-	settings.readAllMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_MATERIALS, false);
-	settings.readMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_MATERIALS, true);
-	settings.readTextures = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_TEXTURES, true);
-	settings.readCameras = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_CAMERAS, true);
-	settings.readLights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_LIGHTS, true);
-	settings.readAnimations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ANIMATIONS, true);
-	settings.strictMode = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_STRICT_MODE, false);
-	settings.preservePivots = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, true);
-	settings.optimizeEmptyAnimationCurves = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES, true);
-	settings.useLegacyEmbeddedTextureNaming = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING, false);
-	settings.removeEmptyBones = pImp->GetPropertyBool(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true);
-	settings.convertToMeters = pImp->GetPropertyBool(AI_CONFIG_FBX_CONVERT_TO_M, false);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure.
-void FBXImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
-	std::unique_ptr<IOStream> stream(pIOHandler->Open(pFile, "rb"));
-	if (!stream) {
-		ThrowException("Could not open file for reading");
-	}
-
-	// read entire file into memory - no streaming for this, fbx
-	// files can grow large, but the assimp output data structure
-	// then becomes very large, too. Assimp doesn't support
-	// streaming for its output data structures so the net win with
-	// streaming input data would be very low.
-	std::vector<char> contents;
-	contents.resize(stream->FileSize() + 1);
-	stream->Read(&*contents.begin(), 1, contents.size() - 1);
-	contents[contents.size() - 1] = 0;
-	const char *const begin = &*contents.begin();
-
-	// broadphase tokenizing pass in which we identify the core
-	// syntax elements of FBX (brackets, commas, key:value mappings)
-	TokenList tokens;
-	try {
-
-		bool is_binary = false;
-		if (!strncmp(begin, "Kaydara FBX Binary", 18)) {
-			is_binary = true;
-			TokenizeBinary(tokens, begin, contents.size());
-		} else {
-			Tokenize(tokens, begin);
-		}
-
-		// use this information to construct a very rudimentary
-		// parse-tree representing the FBX scope structure
-		Parser parser(tokens, is_binary);
-
-		// take the raw parse-tree and convert it to a FBX DOM
-		Document doc(parser, settings);
-
-		// convert the FBX DOM to aiScene
-		ConvertToAssimpScene(pScene, doc, settings.removeEmptyBones);
-
-		// size relative to cm
-		float size_relative_to_cm = doc.GlobalSettings().UnitScaleFactor();
-
-		// Set FBX file scale is relative to CM must be converted to M for
-		// assimp universal format (M)
-		SetFileScale(size_relative_to_cm * 0.01f);
-
-		std::for_each(tokens.begin(), tokens.end(), Util::delete_fun<Token>());
-	} catch (std::exception &) {
-		std::for_each(tokens.begin(), tokens.end(), Util::delete_fun<Token>());
-		throw;
-	}
-}
-
-#endif // !ASSIMP_BUILD_NO_FBX_IMPORTER

+ 0 - 100
thirdparty/assimp/code/FBX/FBXImporter.h

@@ -1,100 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file  FBXImporter.h
- *  @brief Declaration of the FBX main importer class
- */
-#ifndef INCLUDED_AI_FBX_IMPORTER_H
-#define INCLUDED_AI_FBX_IMPORTER_H
-
-#include <assimp/BaseImporter.h>
-#include <assimp/LogAux.h>
-
-#include "FBXImportSettings.h"
-
-namespace Assimp    {
-
-// TinyFormatter.h
-namespace Formatter {
-    template <typename T,typename TR, typename A> class basic_formatter;
-    typedef class basic_formatter< char, std::char_traits<char>, std::allocator<char> > format;
-}
-
-// -------------------------------------------------------------------------------------------
-/** Load the Autodesk FBX file format.
-
- See http://en.wikipedia.org/wiki/FBX
-*/
-// -------------------------------------------------------------------------------------------
-class FBXImporter : public BaseImporter, public LogFunctions<FBXImporter>
-{
-public:
-    FBXImporter();
-    virtual ~FBXImporter();
-
-    // --------------------
-    bool CanRead( const std::string& pFile,
-        IOSystem* pIOHandler,
-        bool checkSig
-    ) const;
-
-protected:
-
-    // --------------------
-    const aiImporterDesc* GetInfo () const;
-
-    // --------------------
-    void SetupProperties(const Importer* pImp);
-
-    // --------------------
-    void InternReadFile( const std::string& pFile,
-        aiScene* pScene,
-        IOSystem* pIOHandler
-    );
-
-private:
-    FBX::ImportSettings settings;
-}; // !class FBXImporter
-
-} // end of namespace Assimp
-#endif // !INCLUDED_AI_FBX_IMPORTER_H
-

+ 0 - 405
thirdparty/assimp/code/FBX/FBXMaterial.cpp

@@ -1,405 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file  FBXMaterial.cpp
- *  @brief Assimp::FBX::Material and Assimp::FBX::Texture implementation
- */
-
-#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
-
-#include "FBXParser.h"
-#include "FBXDocument.h"
-#include "FBXImporter.h"
-#include "FBXImportSettings.h"
-#include "FBXDocumentUtil.h"
-#include "FBXProperties.h"
-#include <assimp/ByteSwapper.h>
-
-#include <algorithm> // std::transform
-#include "FBXUtil.h"
-
-namespace Assimp {
-namespace FBX {
-
-    using namespace Util;
-
-// ------------------------------------------------------------------------------------------------
-Material::Material(uint64_t id, const Element& element, const Document& doc, const std::string& name)
-: Object(id,element,name)
-{
-    const Scope& sc = GetRequiredScope(element);
-
-    const Element* const ShadingModel = sc["ShadingModel"];
-    const Element* const MultiLayer = sc["MultiLayer"];
-
-    if(MultiLayer) {
-        multilayer = !!ParseTokenAsInt(GetRequiredToken(*MultiLayer,0));
-    }
-
-    if(ShadingModel) {
-        shading = ParseTokenAsString(GetRequiredToken(*ShadingModel,0));
-    }
-    else {
-        DOMWarning("shading mode not specified, assuming phong",&element);
-        shading = "phong";
-    }
-
-    std::string templateName;
-
-    // lower-case shading because Blender (for example) writes "Phong"
-    std::transform(shading.begin(), shading.end(), shading.begin(), ::tolower);
-    if(shading == "phong") {
-        templateName = "Material.FbxSurfacePhong";
-    }
-    else if(shading == "lambert") {
-        templateName = "Material.FbxSurfaceLambert";
-    }
-    else {
-        DOMWarning("shading mode not recognized: " + shading,&element);
-    }
-
-    props = GetPropertyTable(doc,templateName,element,sc);
-
-    // resolve texture links
-    const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID());
-    for(const Connection* con : conns) {
-
-        // texture link to properties, not objects
-        if (!con->PropertyName().length()) {
-            continue;
-        }
-
-        const Object* const ob = con->SourceObject();
-        if(!ob) {
-            DOMWarning("failed to read source object for texture link, ignoring",&element);
-            continue;
-        }
-
-        const Texture* const tex = dynamic_cast<const Texture*>(ob);
-        if(!tex) {
-            const LayeredTexture* const layeredTexture = dynamic_cast<const LayeredTexture*>(ob);
-            if(!layeredTexture) {
-                DOMWarning("source object for texture link is not a texture or layered texture, ignoring",&element);
-                continue;
-            }
-            const std::string& prop = con->PropertyName();
-            if (layeredTextures.find(prop) != layeredTextures.end()) {
-                DOMWarning("duplicate layered texture link: " + prop,&element);
-            }
-
-            layeredTextures[prop] = layeredTexture;
-            ((LayeredTexture*)layeredTexture)->fillTexture(doc);
-        }
-        else
-        {
-            const std::string& prop = con->PropertyName();
-            if (textures.find(prop) != textures.end()) {
-                DOMWarning("duplicate texture link: " + prop,&element);
-            }
-
-            textures[prop] = tex;
-        }
-
-    }
-}
-
-
-// ------------------------------------------------------------------------------------------------
-Material::~Material()
-{
-}
-
-
-// ------------------------------------------------------------------------------------------------
-Texture::Texture(uint64_t id, const Element& element, const Document& doc, const std::string& name)
-: Object(id,element,name)
-, uvScaling(1.0f,1.0f)
-, media(0)
-{
-    const Scope& sc = GetRequiredScope(element);
-
-    const Element* const Type = sc["Type"];
-    const Element* const FileName = sc["FileName"];
-    const Element* const RelativeFilename = sc["RelativeFilename"];
-    const Element* const ModelUVTranslation = sc["ModelUVTranslation"];
-    const Element* const ModelUVScaling = sc["ModelUVScaling"];
-    const Element* const Texture_Alpha_Source = sc["Texture_Alpha_Source"];
-    const Element* const Cropping = sc["Cropping"];
-
-    if(Type) {
-        type = ParseTokenAsString(GetRequiredToken(*Type,0));
-    }
-
-    if(FileName) {
-        fileName = ParseTokenAsString(GetRequiredToken(*FileName,0));
-    }
-
-    if(RelativeFilename) {
-        relativeFileName = ParseTokenAsString(GetRequiredToken(*RelativeFilename,0));
-    }
-
-    if(ModelUVTranslation) {
-        uvTrans = aiVector2D(ParseTokenAsFloat(GetRequiredToken(*ModelUVTranslation,0)),
-            ParseTokenAsFloat(GetRequiredToken(*ModelUVTranslation,1))
-        );
-    }
-
-    if(ModelUVScaling) {
-        uvScaling = aiVector2D(ParseTokenAsFloat(GetRequiredToken(*ModelUVScaling,0)),
-            ParseTokenAsFloat(GetRequiredToken(*ModelUVScaling,1))
-        );
-    }
-
-    if(Cropping) {
-        crop[0] = ParseTokenAsInt(GetRequiredToken(*Cropping,0));
-        crop[1] = ParseTokenAsInt(GetRequiredToken(*Cropping,1));
-        crop[2] = ParseTokenAsInt(GetRequiredToken(*Cropping,2));
-        crop[3] = ParseTokenAsInt(GetRequiredToken(*Cropping,3));
-    }
-    else {
-        // vc8 doesn't support the crop() syntax in initialization lists
-        // (and vc9 WARNS about the new (i.e. compliant) behaviour).
-        crop[0] = crop[1] = crop[2] = crop[3] = 0;
-    }
-
-    if(Texture_Alpha_Source) {
-        alphaSource = ParseTokenAsString(GetRequiredToken(*Texture_Alpha_Source,0));
-    }
-
-    props = GetPropertyTable(doc,"Texture.FbxFileTexture",element,sc);
-
-    // 3DS Max and FBX SDK use "Scaling" and "Translation" instead of "ModelUVScaling" and "ModelUVTranslation". Use these properties if available.
-    bool ok;
-    const aiVector3D& scaling = PropertyGet<aiVector3D>(*props, "Scaling", ok);
-    if (ok) {
-        uvScaling.x = scaling.x;
-        uvScaling.y = scaling.y;
-    }
-
-    const aiVector3D& trans = PropertyGet<aiVector3D>(*props, "Translation", ok);
-    if (ok) {
-        uvTrans.x = trans.x;
-        uvTrans.y = trans.y;
-    }
-
-    // resolve video links
-    if(doc.Settings().readTextures) {
-        const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID());
-        for(const Connection* con : conns) {
-            const Object* const ob = con->SourceObject();
-            if(!ob) {
-                DOMWarning("failed to read source object for texture link, ignoring",&element);
-                continue;
-            }
-
-            const Video* const video = dynamic_cast<const Video*>(ob);
-            if(video) {
-                media = video;
-            }
-        }
-    }
-}
-
-
-Texture::~Texture()
-{
-
-}
-
-LayeredTexture::LayeredTexture(uint64_t id, const Element& element, const Document& /*doc*/, const std::string& name)
-: Object(id,element,name)
-,blendMode(BlendMode_Modulate)
-,alpha(1)
-{
-    const Scope& sc = GetRequiredScope(element);
-
-    const Element* const BlendModes = sc["BlendModes"];
-    const Element* const Alphas = sc["Alphas"];
-
-
-    if(BlendModes!=0)
-    {
-        blendMode = (BlendMode)ParseTokenAsInt(GetRequiredToken(*BlendModes,0));
-    }
-    if(Alphas!=0)
-    {
-        alpha = ParseTokenAsFloat(GetRequiredToken(*Alphas,0));
-    }
-}
-
-LayeredTexture::~LayeredTexture()
-{
-    
-}
-
-void LayeredTexture::fillTexture(const Document& doc)
-{
-    const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID());
-    for(size_t i = 0; i < conns.size();++i)
-    {
-        const Connection* con = conns.at(i);
-
-        const Object* const ob = con->SourceObject();
-        if(!ob) {
-            DOMWarning("failed to read source object for texture link, ignoring",&element);
-            continue;
-        }
-
-        const Texture* const tex = dynamic_cast<const Texture*>(ob);
-
-        textures.push_back(tex);
-    }
-}
-
-
-// ------------------------------------------------------------------------------------------------
-Video::Video(uint64_t id, const Element& element, const Document& doc, const std::string& name)
-: Object(id,element,name)
-, contentLength(0)
-, content(0)
-{
-    const Scope& sc = GetRequiredScope(element);
-
-    const Element* const Type = sc["Type"];
-    const Element* const FileName = sc.FindElementCaseInsensitive("FileName");  //some files retain the information as "Filename", others "FileName", who knows
-    const Element* const RelativeFilename = sc["RelativeFilename"];
-    const Element* const Content = sc["Content"];
-
-    if(Type) {
-        type = ParseTokenAsString(GetRequiredToken(*Type,0));
-    }
-
-    if(FileName) {
-        fileName = ParseTokenAsString(GetRequiredToken(*FileName,0));
-    }
-
-    if(RelativeFilename) {
-        relativeFileName = ParseTokenAsString(GetRequiredToken(*RelativeFilename,0));
-    }
-
-    if(Content && !Content->Tokens().empty()) {
-        //this field is omitted when the embedded texture is already loaded, let's ignore if it's not found
-        try {
-            const Token& token = GetRequiredToken(*Content, 0);
-            const char* data = token.begin();
-            if (!token.IsBinary()) {
-                if (*data != '"') {
-                    DOMError("embedded content is not surrounded by quotation marks", &element);
-                }
-                else {
-                    size_t targetLength = 0;
-                    auto numTokens = Content->Tokens().size();
-                    // First time compute size (it could be large like 64Gb and it is good to allocate it once)
-                    for (uint32_t tokenIdx = 0; tokenIdx < numTokens; ++tokenIdx)
-                    {
-                        const Token& dataToken = GetRequiredToken(*Content, tokenIdx);
-                        size_t tokenLength = dataToken.end() - dataToken.begin() - 2; // ignore double quotes
-                        const char* base64data = dataToken.begin() + 1;
-                        const size_t outLength = Util::ComputeDecodedSizeBase64(base64data, tokenLength);
-                        if (outLength == 0)
-                        {
-                            DOMError("Corrupted embedded content found", &element);
-                        }
-                        targetLength += outLength;
-                    }
-                    if (targetLength == 0)
-                    {
-                        DOMError("Corrupted embedded content found", &element);
-                    }
-                    content = new uint8_t[targetLength];
-                    contentLength = static_cast<uint64_t>(targetLength);
-                    size_t dst_offset = 0;
-                    for (uint32_t tokenIdx = 0; tokenIdx < numTokens; ++tokenIdx)
-                    {
-                        const Token& dataToken = GetRequiredToken(*Content, tokenIdx);
-                        size_t tokenLength = dataToken.end() - dataToken.begin() - 2; // ignore double quotes
-                        const char* base64data = dataToken.begin() + 1;
-                        dst_offset += Util::DecodeBase64(base64data, tokenLength, content + dst_offset, targetLength - dst_offset);
-                    }
-                    if (targetLength != dst_offset)
-                    {
-                        delete[] content;
-                        contentLength = 0;
-                        DOMError("Corrupted embedded content found", &element);
-                    }
-                }
-            }
-            else if (static_cast<size_t>(token.end() - data) < 5) {
-                DOMError("binary data array is too short, need five (5) bytes for type signature and element count", &element);
-            }
-            else if (*data != 'R') {
-                DOMWarning("video content is not raw binary data, ignoring", &element);
-            }
-            else {
-                // read number of elements
-                uint32_t len = 0;
-                ::memcpy(&len, data + 1, sizeof(len));
-                AI_SWAP4(len);
-
-                contentLength = len;
-
-                content = new uint8_t[len];
-                ::memcpy(content, data + 5, len);
-            }
-        } catch (const runtime_error& runtimeError)
-        {
-            //we don't need the content data for contents that has already been loaded
-            ASSIMP_LOG_DEBUG_F("Caught exception in FBXMaterial (likely because content was already loaded): ",
-                    runtimeError.what());
-        }
-    }
-
-    props = GetPropertyTable(doc,"Video.FbxVideo",element,sc);
-}
-
-
-Video::~Video()
-{
-    if(content) {
-        delete[] content;
-    }
-}
-
-} //!FBX
-} //!Assimp
-
-#endif

+ 0 - 709
thirdparty/assimp/code/FBX/FBXMeshGeometry.cpp

@@ -1,709 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file  FBXMeshGeometry.cpp
- *  @brief Assimp::FBX::MeshGeometry implementation
- */
-
-#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
-
-#include <functional>
-
-#include "FBXMeshGeometry.h"
-#include "FBXDocument.h"
-#include "FBXImporter.h"
-#include "FBXImportSettings.h"
-#include "FBXDocumentUtil.h"
-
-
-namespace Assimp {
-namespace FBX {
-
-using namespace Util;
-
-// ------------------------------------------------------------------------------------------------
-Geometry::Geometry(uint64_t id, const Element& element, const std::string& name, const Document& doc)
-    : Object(id, element, name)
-    , skin()
-{
-    const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"Deformer");
-    for(const Connection* con : conns) {
-        const Skin* const sk = ProcessSimpleConnection<Skin>(*con, false, "Skin -> Geometry", element);
-        if(sk) {
-            skin = sk;
-        }
-        const BlendShape* const bsp = ProcessSimpleConnection<BlendShape>(*con, false, "BlendShape -> Geometry", element);
-        if (bsp) {
-            blendShapes.push_back(bsp);
-        }
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-Geometry::~Geometry()
-{
-    // empty
-}
-
-// ------------------------------------------------------------------------------------------------
-const std::vector<const BlendShape*>& Geometry::GetBlendShapes() const {
-    return blendShapes;
-}
-
-// ------------------------------------------------------------------------------------------------
-const Skin* Geometry::DeformerSkin() const {
-    return skin;
-}
-
-// ------------------------------------------------------------------------------------------------
-MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc)
-: Geometry(id, element,name, doc)
-{
-    const Scope* sc = element.Compound();
-    if (!sc) {
-        DOMError("failed to read Geometry object (class: Mesh), no data scope found");
-    }
-
-    // must have Mesh elements:
-    const Element& Vertices = GetRequiredElement(*sc,"Vertices",&element);
-    const Element& PolygonVertexIndex = GetRequiredElement(*sc,"PolygonVertexIndex",&element);
-
-    // optional Mesh elements:
-    const ElementCollection& Layer = sc->GetCollection("Layer");
-
-    std::vector<aiVector3D> tempVerts;
-    ParseVectorDataArray(tempVerts,Vertices);
-
-    if(tempVerts.empty()) {
-        FBXImporter::LogWarn("encountered mesh with no vertices");
-    }
-
-    std::vector<int> tempFaces;
-    ParseVectorDataArray(tempFaces,PolygonVertexIndex);
-
-    if(tempFaces.empty()) {
-        FBXImporter::LogWarn("encountered mesh with no faces");
-    }
-
-    m_vertices.reserve(tempFaces.size());
-    m_faces.reserve(tempFaces.size() / 3);
-
-    m_mapping_offsets.resize(tempVerts.size());
-    m_mapping_counts.resize(tempVerts.size(),0);
-    m_mappings.resize(tempFaces.size());
-
-    const size_t vertex_count = tempVerts.size();
-
-    // generate output vertices, computing an adjacency table to
-    // preserve the mapping from fbx indices to *this* indexing.
-    unsigned int count = 0;
-    for(int index : tempFaces) {
-        const int absi = index < 0 ? (-index - 1) : index;
-        if(static_cast<size_t>(absi) >= vertex_count) {
-            DOMError("polygon vertex index out of range",&PolygonVertexIndex);
-        }
-
-        m_vertices.push_back(tempVerts[absi]);
-        ++count;
-
-        ++m_mapping_counts[absi];
-
-        if (index < 0) {
-            m_faces.push_back(count);
-            count = 0;
-        }
-    }
-
-    unsigned int cursor = 0;
-    for (size_t i = 0, e = tempVerts.size(); i < e; ++i) {
-        m_mapping_offsets[i] = cursor;
-        cursor += m_mapping_counts[i];
-
-        m_mapping_counts[i] = 0;
-    }
-
-    cursor = 0;
-    for(int index : tempFaces) {
-        const int absi = index < 0 ? (-index - 1) : index;
-        m_mappings[m_mapping_offsets[absi] + m_mapping_counts[absi]++] = cursor++;
-    }
-
-    // if settings.readAllLayers is true:
-    //  * read all layers, try to load as many vertex channels as possible
-    // if settings.readAllLayers is false:
-    //  * read only the layer with index 0, but warn about any further layers
-    for (ElementMap::const_iterator it = Layer.first; it != Layer.second; ++it) {
-        const TokenList& tokens = (*it).second->Tokens();
-
-        const char* err;
-        const int index = ParseTokenAsInt(*tokens[0], err);
-        if(err) {
-            DOMError(err,&element);
-        }
-
-        if(doc.Settings().readAllLayers || index == 0) {
-            const Scope& layer = GetRequiredScope(*(*it).second);
-            ReadLayer(layer);
-        }
-        else {
-            FBXImporter::LogWarn("ignoring additional geometry layers");
-        }
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-MeshGeometry::~MeshGeometry() {
-    // empty
-}
-
-// ------------------------------------------------------------------------------------------------
-const std::vector<aiVector3D>& MeshGeometry::GetVertices() const {
-    return m_vertices;
-}
-
-// ------------------------------------------------------------------------------------------------
-const std::vector<aiVector3D>& MeshGeometry::GetNormals() const {
-    return m_normals;
-}
-
-// ------------------------------------------------------------------------------------------------
-const std::vector<aiVector3D>& MeshGeometry::GetTangents() const {
-    return m_tangents;
-}
-
-// ------------------------------------------------------------------------------------------------
-const std::vector<aiVector3D>& MeshGeometry::GetBinormals() const {
-    return m_binormals;
-}
-
-// ------------------------------------------------------------------------------------------------
-const std::vector<unsigned int>& MeshGeometry::GetFaceIndexCounts() const {
-    return m_faces;
-}
-
-// ------------------------------------------------------------------------------------------------
-const std::vector<aiVector2D>& MeshGeometry::GetTextureCoords( unsigned int index ) const {
-    static const std::vector<aiVector2D> empty;
-    return index >= AI_MAX_NUMBER_OF_TEXTURECOORDS ? empty : m_uvs[ index ];
-}
-
-std::string MeshGeometry::GetTextureCoordChannelName( unsigned int index ) const {
-    return index >= AI_MAX_NUMBER_OF_TEXTURECOORDS ? "" : m_uvNames[ index ];
-}
-
-const std::vector<aiColor4D>& MeshGeometry::GetVertexColors( unsigned int index ) const {
-    static const std::vector<aiColor4D> empty;
-    return index >= AI_MAX_NUMBER_OF_COLOR_SETS ? empty : m_colors[ index ];
-}
-
-const MatIndexArray& MeshGeometry::GetMaterialIndices() const {
-    return m_materials;
-}
-// ------------------------------------------------------------------------------------------------
-const unsigned int* MeshGeometry::ToOutputVertexIndex( unsigned int in_index, unsigned int& count ) const {
-    if ( in_index >= m_mapping_counts.size() ) {
-        return NULL;
-    }
-
-    ai_assert( m_mapping_counts.size() == m_mapping_offsets.size() );
-    count = m_mapping_counts[ in_index ];
-
-    ai_assert( m_mapping_offsets[ in_index ] + count <= m_mappings.size() );
-
-    return &m_mappings[ m_mapping_offsets[ in_index ] ];
-}
-
-// ------------------------------------------------------------------------------------------------
-unsigned int MeshGeometry::FaceForVertexIndex( unsigned int in_index ) const {
-    ai_assert( in_index < m_vertices.size() );
-
-    // in the current conversion pattern this will only be needed if
-    // weights are present, so no need to always pre-compute this table
-    if ( m_facesVertexStartIndices.empty() ) {
-        m_facesVertexStartIndices.resize( m_faces.size() + 1, 0 );
-
-        std::partial_sum( m_faces.begin(), m_faces.end(), m_facesVertexStartIndices.begin() + 1 );
-        m_facesVertexStartIndices.pop_back();
-    }
-
-    ai_assert( m_facesVertexStartIndices.size() == m_faces.size() );
-    const std::vector<unsigned int>::iterator it = std::upper_bound(
-        m_facesVertexStartIndices.begin(),
-        m_facesVertexStartIndices.end(),
-        in_index
-        );
-
-    return static_cast< unsigned int >( std::distance( m_facesVertexStartIndices.begin(), it - 1 ) );
-}
-
-// ------------------------------------------------------------------------------------------------
-void MeshGeometry::ReadLayer(const Scope& layer)
-{
-    const ElementCollection& LayerElement = layer.GetCollection("LayerElement");
-    for (ElementMap::const_iterator eit = LayerElement.first; eit != LayerElement.second; ++eit) {
-        const Scope& elayer = GetRequiredScope(*(*eit).second);
-
-        ReadLayerElement(elayer);
-    }
-}
-
-
-// ------------------------------------------------------------------------------------------------
-void MeshGeometry::ReadLayerElement(const Scope& layerElement)
-{
-    const Element& Type = GetRequiredElement(layerElement,"Type");
-    const Element& TypedIndex = GetRequiredElement(layerElement,"TypedIndex");
-
-    const std::string& type = ParseTokenAsString(GetRequiredToken(Type,0));
-    const int typedIndex = ParseTokenAsInt(GetRequiredToken(TypedIndex,0));
-
-    const Scope& top = GetRequiredScope(element);
-    const ElementCollection candidates = top.GetCollection(type);
-
-    for (ElementMap::const_iterator it = candidates.first; it != candidates.second; ++it) {
-        const int index = ParseTokenAsInt(GetRequiredToken(*(*it).second,0));
-        if(index == typedIndex) {
-            ReadVertexData(type,typedIndex,GetRequiredScope(*(*it).second));
-            return;
-        }
-    }
-
-    FBXImporter::LogError(Formatter::format("failed to resolve vertex layer element: ")
-        << type << ", index: " << typedIndex);
-}
-
-// ------------------------------------------------------------------------------------------------
-void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scope& source)
-{
-    const std::string& MappingInformationType = ParseTokenAsString(GetRequiredToken(
-        GetRequiredElement(source,"MappingInformationType"),0)
-    );
-
-    const std::string& ReferenceInformationType = ParseTokenAsString(GetRequiredToken(
-        GetRequiredElement(source,"ReferenceInformationType"),0)
-    );
-
-    if (type == "LayerElementUV") {
-        if(index >= AI_MAX_NUMBER_OF_TEXTURECOORDS) {
-            FBXImporter::LogError(Formatter::format("ignoring UV layer, maximum number of UV channels exceeded: ")
-                << index << " (limit is " << AI_MAX_NUMBER_OF_TEXTURECOORDS << ")" );
-            return;
-        }
-
-        const Element* Name = source["Name"];
-        m_uvNames[index] = "";
-        if(Name) {
-            m_uvNames[index] = ParseTokenAsString(GetRequiredToken(*Name,0));
-        }
-
-        ReadVertexDataUV(m_uvs[index],source,
-            MappingInformationType,
-            ReferenceInformationType
-        );
-    }
-    else if (type == "LayerElementMaterial") {
-        if (m_materials.size() > 0) {
-            FBXImporter::LogError("ignoring additional material layer");
-            return;
-        }
-
-        std::vector<int> temp_materials;
-
-        ReadVertexDataMaterials(temp_materials,source,
-            MappingInformationType,
-            ReferenceInformationType
-        );
-
-        // sometimes, there will be only negative entries. Drop the material
-        // layer in such a case (I guess it means a default material should
-        // be used). This is what the converter would do anyway, and it
-        // avoids losing the material if there are more material layers
-        // coming of which at least one contains actual data (did observe
-        // that with one test file).
-        const size_t count_neg = std::count_if(temp_materials.begin(),temp_materials.end(),[](int n) { return n < 0; });
-        if(count_neg == temp_materials.size()) {
-            FBXImporter::LogWarn("ignoring dummy material layer (all entries -1)");
-            return;
-        }
-
-        std::swap(temp_materials, m_materials);
-    }
-    else if (type == "LayerElementNormal") {
-        if (m_normals.size() > 0) {
-            FBXImporter::LogError("ignoring additional normal layer");
-            return;
-        }
-
-        ReadVertexDataNormals(m_normals,source,
-            MappingInformationType,
-            ReferenceInformationType
-        );
-    }
-    else if (type == "LayerElementTangent") {
-        if (m_tangents.size() > 0) {
-            FBXImporter::LogError("ignoring additional tangent layer");
-            return;
-        }
-
-        ReadVertexDataTangents(m_tangents,source,
-            MappingInformationType,
-            ReferenceInformationType
-        );
-    }
-    else if (type == "LayerElementBinormal") {
-        if (m_binormals.size() > 0) {
-            FBXImporter::LogError("ignoring additional binormal layer");
-            return;
-        }
-
-        ReadVertexDataBinormals(m_binormals,source,
-            MappingInformationType,
-            ReferenceInformationType
-        );
-    }
-    else if (type == "LayerElementColor") {
-        if(index >= AI_MAX_NUMBER_OF_COLOR_SETS) {
-            FBXImporter::LogError(Formatter::format("ignoring vertex color layer, maximum number of color sets exceeded: ")
-                << index << " (limit is " << AI_MAX_NUMBER_OF_COLOR_SETS << ")" );
-            return;
-        }
-
-        ReadVertexDataColors(m_colors[index],source,
-            MappingInformationType,
-            ReferenceInformationType
-        );
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-// Lengthy utility function to read and resolve a FBX vertex data array - that is, the
-// output is in polygon vertex order. This logic is used for reading normals, UVs, colors,
-// tangents ..
-template <typename T>
-void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
-    const std::string& MappingInformationType,
-    const std::string& ReferenceInformationType,
-    const char* dataElementName,
-    const char* indexDataElementName,
-    size_t vertex_count,
-    const std::vector<unsigned int>& mapping_counts,
-    const std::vector<unsigned int>& mapping_offsets,
-    const std::vector<unsigned int>& mappings)
-{
-    bool isDirect = ReferenceInformationType == "Direct";
-    bool isIndexToDirect = ReferenceInformationType == "IndexToDirect";
-
-    // fall-back to direct data if there is no index data element
-    if ( isIndexToDirect && !HasElement( source, indexDataElementName ) ) {
-        isDirect = true;
-        isIndexToDirect = false;
-    }
-
-    // handle permutations of Mapping and Reference type - it would be nice to
-    // deal with this more elegantly and with less redundancy, but right
-    // now it seems unavoidable.
-    if (MappingInformationType == "ByVertice" && isDirect) {
-        if (!HasElement(source, dataElementName)) {
-            return;
-        }
-        std::vector<T> tempData;
-		ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
-
-        data_out.resize(vertex_count);
-		for (size_t i = 0, e = tempData.size(); i < e; ++i) {
-
-            const unsigned int istart = mapping_offsets[i], iend = istart + mapping_counts[i];
-            for (unsigned int j = istart; j < iend; ++j) {
-				data_out[mappings[j]] = tempData[i];
-            }
-        }
-    }
-    else if (MappingInformationType == "ByVertice" && isIndexToDirect) {
-		std::vector<T> tempData;
-		ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
-
-        data_out.resize(vertex_count);
-
-        std::vector<int> uvIndices;
-        ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName));
-        for (size_t i = 0, e = uvIndices.size(); i < e; ++i) {
-
-            const unsigned int istart = mapping_offsets[i], iend = istart + mapping_counts[i];
-            for (unsigned int j = istart; j < iend; ++j) {
-				if (static_cast<size_t>(uvIndices[i]) >= tempData.size()) {
-                    DOMError("index out of range",&GetRequiredElement(source,indexDataElementName));
-                }
-				data_out[mappings[j]] = tempData[uvIndices[i]];
-            }
-        }
-    }
-    else if (MappingInformationType == "ByPolygonVertex" && isDirect) {
-		std::vector<T> tempData;
-		ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
-
-		if (tempData.size() != vertex_count) {
-            FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygon mapping: ")
-				<< tempData.size() << ", expected " << vertex_count
-            );
-            return;
-        }
-
-		data_out.swap(tempData);
-    }
-    else if (MappingInformationType == "ByPolygonVertex" && isIndexToDirect) {
-		std::vector<T> tempData;
-		ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
-
-        data_out.resize(vertex_count);
-
-        std::vector<int> uvIndices;
-        ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName));
-
-        if (uvIndices.size() != vertex_count) {
-            FBXImporter::LogError("length of input data unexpected for ByPolygonVertex mapping");
-            return;
-        }
-
-        const T empty;
-        unsigned int next = 0;
-        for(int i : uvIndices) {
-            if ( -1 == i ) {
-                data_out[ next++ ] = empty;
-                continue;
-            }
-            if (static_cast<size_t>(i) >= tempData.size()) {
-                DOMError("index out of range",&GetRequiredElement(source,indexDataElementName));
-            }
-
-			data_out[next++] = tempData[i];
-        }
-    }
-    else {
-        FBXImporter::LogError(Formatter::format("ignoring vertex data channel, access type not implemented: ")
-            << MappingInformationType << "," << ReferenceInformationType);
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-void MeshGeometry::ReadVertexDataNormals(std::vector<aiVector3D>& normals_out, const Scope& source,
-    const std::string& MappingInformationType,
-    const std::string& ReferenceInformationType)
-{
-    ResolveVertexDataArray(normals_out,source,MappingInformationType,ReferenceInformationType,
-        "Normals",
-        "NormalsIndex",
-        m_vertices.size(),
-        m_mapping_counts,
-        m_mapping_offsets,
-        m_mappings);
-}
-
-// ------------------------------------------------------------------------------------------------
-void MeshGeometry::ReadVertexDataUV(std::vector<aiVector2D>& uv_out, const Scope& source,
-    const std::string& MappingInformationType,
-    const std::string& ReferenceInformationType)
-{
-    ResolveVertexDataArray(uv_out,source,MappingInformationType,ReferenceInformationType,
-        "UV",
-        "UVIndex",
-        m_vertices.size(),
-        m_mapping_counts,
-        m_mapping_offsets,
-        m_mappings);
-}
-
-// ------------------------------------------------------------------------------------------------
-void MeshGeometry::ReadVertexDataColors(std::vector<aiColor4D>& colors_out, const Scope& source,
-    const std::string& MappingInformationType,
-    const std::string& ReferenceInformationType)
-{
-    ResolveVertexDataArray(colors_out,source,MappingInformationType,ReferenceInformationType,
-        "Colors",
-        "ColorIndex",
-        m_vertices.size(),
-        m_mapping_counts,
-        m_mapping_offsets,
-        m_mappings);
-}
-
-// ------------------------------------------------------------------------------------------------
-static const char *TangentIndexToken = "TangentIndex";
-static const char *TangentsIndexToken = "TangentsIndex";
-
-void MeshGeometry::ReadVertexDataTangents(std::vector<aiVector3D>& tangents_out, const Scope& source,
-    const std::string& MappingInformationType,
-    const std::string& ReferenceInformationType)
-{
-    const char * str = source.Elements().count( "Tangents" ) > 0 ? "Tangents" : "Tangent";
-    const char * strIdx = source.Elements().count( "Tangents" ) > 0 ? TangentsIndexToken : TangentIndexToken;
-    ResolveVertexDataArray(tangents_out,source,MappingInformationType,ReferenceInformationType,
-        str,
-        strIdx,
-        m_vertices.size(),
-        m_mapping_counts,
-        m_mapping_offsets,
-        m_mappings);
-}
-
-// ------------------------------------------------------------------------------------------------
-static const std::string BinormalIndexToken = "BinormalIndex";
-static const std::string BinormalsIndexToken = "BinormalsIndex";
-
-void MeshGeometry::ReadVertexDataBinormals(std::vector<aiVector3D>& binormals_out, const Scope& source,
-    const std::string& MappingInformationType,
-    const std::string& ReferenceInformationType)
-{
-    const char * str = source.Elements().count( "Binormals" ) > 0 ? "Binormals" : "Binormal";
-    const char * strIdx = source.Elements().count( "Binormals" ) > 0 ? BinormalsIndexToken.c_str() : BinormalIndexToken.c_str();
-    ResolveVertexDataArray(binormals_out,source,MappingInformationType,ReferenceInformationType,
-        str,
-        strIdx,
-        m_vertices.size(),
-        m_mapping_counts,
-        m_mapping_offsets,
-        m_mappings);
-}
-
-
-// ------------------------------------------------------------------------------------------------
-void MeshGeometry::ReadVertexDataMaterials(std::vector<int>& materials_out, const Scope& source,
-    const std::string& MappingInformationType,
-    const std::string& ReferenceInformationType)
-{
-    const size_t face_count = m_faces.size();
-    if( 0 == face_count )
-    {
-        return;
-    }
-    
-    // materials are handled separately. First of all, they are assigned per-face
-    // and not per polyvert. Secondly, ReferenceInformationType=IndexToDirect
-    // has a slightly different meaning for materials.
-    ParseVectorDataArray(materials_out,GetRequiredElement(source,"Materials"));
-
-    if (MappingInformationType == "AllSame") {
-        // easy - same material for all faces
-        if (materials_out.empty()) {
-            FBXImporter::LogError(Formatter::format("expected material index, ignoring"));
-            return;
-        } else if (materials_out.size() > 1) {
-            FBXImporter::LogWarn(Formatter::format("expected only a single material index, ignoring all except the first one"));
-            materials_out.clear();
-        }
-
-        materials_out.resize(m_vertices.size());
-        std::fill(materials_out.begin(), materials_out.end(), materials_out.at(0));
-    } else if (MappingInformationType == "ByPolygon" && ReferenceInformationType == "IndexToDirect") {
-        materials_out.resize(face_count);
-
-        if(materials_out.size() != face_count) {
-            FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygon mapping: ")
-                << materials_out.size() << ", expected " << face_count
-            );
-            return;
-        }
-    } else {
-        FBXImporter::LogError(Formatter::format("ignoring material assignments, access type not implemented: ")
-            << MappingInformationType << "," << ReferenceInformationType);
-    }
-}
-// ------------------------------------------------------------------------------------------------
-ShapeGeometry::ShapeGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc)
-: Geometry(id, element, name, doc) {
-    const Scope *sc = element.Compound();
-    if (nullptr == sc) {
-        DOMError("failed to read Geometry object (class: Shape), no data scope found");
-    }
-    const Element& Indexes = GetRequiredElement(*sc, "Indexes", &element);
-    const Element& Normals = GetRequiredElement(*sc, "Normals", &element);
-    const Element& Vertices = GetRequiredElement(*sc, "Vertices", &element);
-    ParseVectorDataArray(m_indices, Indexes);
-    ParseVectorDataArray(m_vertices, Vertices);
-    ParseVectorDataArray(m_normals, Normals);
-}
-
-// ------------------------------------------------------------------------------------------------
-ShapeGeometry::~ShapeGeometry() {
-    // empty
-}
-// ------------------------------------------------------------------------------------------------
-const std::vector<aiVector3D>& ShapeGeometry::GetVertices() const {
-    return m_vertices;
-}
-// ------------------------------------------------------------------------------------------------
-const std::vector<aiVector3D>& ShapeGeometry::GetNormals() const {
-    return m_normals;
-}
-// ------------------------------------------------------------------------------------------------
-const std::vector<unsigned int>& ShapeGeometry::GetIndices() const {
-    return m_indices;
-}
-// ------------------------------------------------------------------------------------------------
-LineGeometry::LineGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc)
-    : Geometry(id, element, name, doc)
-{
-    const Scope* sc = element.Compound();
-    if (!sc) {
-        DOMError("failed to read Geometry object (class: Line), no data scope found");
-    }
-    const Element& Points = GetRequiredElement(*sc, "Points", &element);
-    const Element& PointsIndex = GetRequiredElement(*sc, "PointsIndex", &element);
-    ParseVectorDataArray(m_vertices, Points);
-    ParseVectorDataArray(m_indices, PointsIndex);
-}
-
-// ------------------------------------------------------------------------------------------------
-LineGeometry::~LineGeometry() {
-    // empty
-}
-// ------------------------------------------------------------------------------------------------
-const std::vector<aiVector3D>& LineGeometry::GetVertices() const {
-    return m_vertices;
-}
-// ------------------------------------------------------------------------------------------------
-const std::vector<int>& LineGeometry::GetIndices() const {
-    return m_indices;
-}
-} // !FBX
-} // !Assimp
-#endif
-

+ 0 - 235
thirdparty/assimp/code/FBX/FBXMeshGeometry.h

@@ -1,235 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-copyright notice, this list of conditions and the
-following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the
-following disclaimer in the documentation and/or other
-materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-contributors may be used to endorse or promote products
-derived from this software without specific prior
-written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file  FBXImporter.h
-*  @brief Declaration of the FBX main importer class
-*/
-#ifndef INCLUDED_AI_FBX_MESHGEOMETRY_H
-#define INCLUDED_AI_FBX_MESHGEOMETRY_H
-
-#include "FBXParser.h"
-#include "FBXDocument.h"
-
-namespace Assimp {
-namespace FBX {
-
-/** 
- *  DOM base class for all kinds of FBX geometry 
- */
-class Geometry : public Object
-{
-public:
-    Geometry( uint64_t id, const Element& element, const std::string& name, const Document& doc );
-    virtual ~Geometry();
-
-    /** Get the Skin attached to this geometry or NULL */
-    const Skin* DeformerSkin() const;
-
-    /** Get the BlendShape attached to this geometry or NULL */
-    const std::vector<const BlendShape*>& GetBlendShapes() const;
-
-private:
-    const Skin* skin;
-    std::vector<const BlendShape*> blendShapes;
-
-};
-
-typedef std::vector<int> MatIndexArray;
-
-
-/** 
- *  DOM class for FBX geometry of type "Mesh"
- */
-class MeshGeometry : public Geometry
-{
-public:
-    /** The class constructor */
-    MeshGeometry( uint64_t id, const Element& element, const std::string& name, const Document& doc );
-    
-    /** The class destructor */
-    virtual ~MeshGeometry();
-
-    /** Get a list of all vertex points, non-unique*/
-    const std::vector<aiVector3D>& GetVertices() const;
-
-    /** Get a list of all vertex normals or an empty array if
-    *  no normals are specified. */
-    const std::vector<aiVector3D>& GetNormals() const;
-
-    /** Get a list of all vertex tangents or an empty array
-    *  if no tangents are specified */
-    const std::vector<aiVector3D>& GetTangents() const;
-
-    /** Get a list of all vertex bi-normals or an empty array
-    *  if no bi-normals are specified */
-    const std::vector<aiVector3D>& GetBinormals() const;
-
-    /** Return list of faces - each entry denotes a face and specifies
-    *  how many vertices it has. Vertices are taken from the
-    *  vertex data arrays in sequential order. */
-    const std::vector<unsigned int>& GetFaceIndexCounts() const;
-
-    /** Get a UV coordinate slot, returns an empty array if
-    *  the requested slot does not exist. */
-    const std::vector<aiVector2D>& GetTextureCoords( unsigned int index ) const;
-
-    /** Get a UV coordinate slot, returns an empty array if
-    *  the requested slot does not exist. */
-    std::string GetTextureCoordChannelName( unsigned int index ) const;
-
-    /** Get a vertex color coordinate slot, returns an empty array if
-    *  the requested slot does not exist. */
-    const std::vector<aiColor4D>& GetVertexColors( unsigned int index ) const;
-
-    /** Get per-face-vertex material assignments */
-    const MatIndexArray& GetMaterialIndices() const;
-
-    /** Convert from a fbx file vertex index (for example from a #Cluster weight) or NULL
-    * if the vertex index is not valid. */
-    const unsigned int* ToOutputVertexIndex( unsigned int in_index, unsigned int& count ) const;
-
-    /** Determine the face to which a particular output vertex index belongs.
-    *  This mapping is always unique. */
-    unsigned int FaceForVertexIndex( unsigned int in_index ) const;
-private:
-    void ReadLayer( const Scope& layer );
-    void ReadLayerElement( const Scope& layerElement );
-    void ReadVertexData( const std::string& type, int index, const Scope& source );
-
-    void ReadVertexDataUV( std::vector<aiVector2D>& uv_out, const Scope& source,
-        const std::string& MappingInformationType,
-        const std::string& ReferenceInformationType );
-
-    void ReadVertexDataNormals( std::vector<aiVector3D>& normals_out, const Scope& source,
-        const std::string& MappingInformationType,
-        const std::string& ReferenceInformationType );
-
-    void ReadVertexDataColors( std::vector<aiColor4D>& colors_out, const Scope& source,
-        const std::string& MappingInformationType,
-        const std::string& ReferenceInformationType );
-
-    void ReadVertexDataTangents( std::vector<aiVector3D>& tangents_out, const Scope& source,
-        const std::string& MappingInformationType,
-        const std::string& ReferenceInformationType );
-
-    void ReadVertexDataBinormals( std::vector<aiVector3D>& binormals_out, const Scope& source,
-        const std::string& MappingInformationType,
-        const std::string& ReferenceInformationType );
-
-    void ReadVertexDataMaterials( MatIndexArray& materials_out, const Scope& source,
-        const std::string& MappingInformationType,
-        const std::string& ReferenceInformationType );
-
-private:
-    // cached data arrays
-    MatIndexArray m_materials;
-    std::vector<aiVector3D> m_vertices;
-    std::vector<unsigned int> m_faces;
-    mutable std::vector<unsigned int> m_facesVertexStartIndices;
-    std::vector<aiVector3D> m_tangents;
-    std::vector<aiVector3D> m_binormals;
-    std::vector<aiVector3D> m_normals;
-
-    std::string m_uvNames[ AI_MAX_NUMBER_OF_TEXTURECOORDS ];
-    std::vector<aiVector2D> m_uvs[ AI_MAX_NUMBER_OF_TEXTURECOORDS ];
-    std::vector<aiColor4D> m_colors[ AI_MAX_NUMBER_OF_COLOR_SETS ];
-
-    std::vector<unsigned int> m_mapping_counts;
-    std::vector<unsigned int> m_mapping_offsets;
-    std::vector<unsigned int> m_mappings;
-};
-
-/**
-*  DOM class for FBX geometry of type "Shape"
-*/
-class ShapeGeometry : public Geometry
-{
-public:
-    /** The class constructor */
-    ShapeGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc);
-
-    /** The class destructor */
-    virtual ~ShapeGeometry();
-
-    /** Get a list of all vertex points, non-unique*/
-    const std::vector<aiVector3D>& GetVertices() const;
-
-    /** Get a list of all vertex normals or an empty array if
-    *  no normals are specified. */
-    const std::vector<aiVector3D>& GetNormals() const;
-
-    /** Return list of vertex indices. */
-    const std::vector<unsigned int>& GetIndices() const;
-
-private:
-    std::vector<aiVector3D> m_vertices;
-    std::vector<aiVector3D> m_normals;
-    std::vector<unsigned int> m_indices;
-};
-/**
-*  DOM class for FBX geometry of type "Line"
-*/
-class LineGeometry : public Geometry
-{
-public:
-    /** The class constructor */
-    LineGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc);
-
-    /** The class destructor */
-    virtual ~LineGeometry();
-
-    /** Get a list of all vertex points, non-unique*/
-    const std::vector<aiVector3D>& GetVertices() const;
-
-    /** Return list of vertex indices. */
-    const std::vector<int>& GetIndices() const;
-
-private:
-    std::vector<aiVector3D> m_vertices;
-    std::vector<int> m_indices;
-};
-
-}
-}
-
-#endif // INCLUDED_AI_FBX_MESHGEOMETRY_H
-

+ 0 - 153
thirdparty/assimp/code/FBX/FBXModel.cpp

@@ -1,153 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file  FBXModel.cpp
- *  @brief Assimp::FBX::Model implementation
- */
-
-#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
-
-#include "FBXParser.h"
-#include "FBXMeshGeometry.h"
-#include "FBXDocument.h"
-#include "FBXImporter.h"
-#include "FBXDocumentUtil.h"
-
-namespace Assimp {
-namespace FBX {
-
-using namespace Util;
-
-// ------------------------------------------------------------------------------------------------
-Model::Model(uint64_t id, const Element& element, const Document& doc, const std::string& name)
-    : Object(id,element,name)
-    , shading("Y")
-{
-    const Scope& sc = GetRequiredScope(element);
-    const Element* const Shading = sc["Shading"];
-    const Element* const Culling = sc["Culling"];
-
-    if(Shading) {
-        shading = GetRequiredToken(*Shading,0).StringContents();
-    }
-
-    if (Culling) {
-        culling = ParseTokenAsString(GetRequiredToken(*Culling,0));
-    }
-
-    props = GetPropertyTable(doc,"Model.FbxNode",element,sc);
-    ResolveLinks(element,doc);
-}
-
-// ------------------------------------------------------------------------------------------------
-Model::~Model()
-{
-
-}
-
-// ------------------------------------------------------------------------------------------------
-void Model::ResolveLinks(const Element& element, const Document& doc)
-{
-    const char* const arr[] = {"Geometry","Material","NodeAttribute"};
-
-    // resolve material
-    const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),arr, 3);
-
-    materials.reserve(conns.size());
-    geometry.reserve(conns.size());
-    attributes.reserve(conns.size());
-    for(const Connection* con : conns) {
-
-        // material and geometry links should be Object-Object connections
-        if (con->PropertyName().length()) {
-            continue;
-        }
-
-        const Object* const ob = con->SourceObject();
-        if(!ob) {
-            DOMWarning("failed to read source object for incoming Model link, ignoring",&element);
-            continue;
-        }
-
-        const Material* const mat = dynamic_cast<const Material*>(ob);
-        if(mat) {
-            materials.push_back(mat);
-            continue;
-        }
-
-        const Geometry* const geo = dynamic_cast<const Geometry*>(ob);
-        if(geo) {
-            geometry.push_back(geo);
-            continue;
-        }
-
-        const NodeAttribute* const att = dynamic_cast<const NodeAttribute*>(ob);
-        if(att) {
-            attributes.push_back(att);
-            continue;
-        }
-
-        DOMWarning("source object for model link is neither Material, NodeAttribute nor Geometry, ignoring",&element);
-        continue;
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-bool Model::IsNull() const
-{
-    const std::vector<const NodeAttribute*>& attrs = GetAttributes();
-    for(const NodeAttribute* att : attrs) {
-
-        const Null* null_tag = dynamic_cast<const Null*>(att);
-        if(null_tag) {
-            return true;
-        }
-    }
-
-    return false;
-}
-
-
-} //!FBX
-} //!Assimp
-
-#endif

+ 0 - 170
thirdparty/assimp/code/FBX/FBXNodeAttribute.cpp

@@ -1,170 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file  FBXNoteAttribute.cpp
- *  @brief Assimp::FBX::NodeAttribute (and subclasses) implementation
- */
-
-#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
-
-#include "FBXParser.h"
-#include "FBXDocument.h"
-#include "FBXImporter.h"
-#include "FBXDocumentUtil.h"
-
-namespace Assimp {
-namespace FBX {
-
-using namespace Util;
-
-// ------------------------------------------------------------------------------------------------
-NodeAttribute::NodeAttribute(uint64_t id, const Element& element, const Document& doc, const std::string& name)
-: Object(id,element,name)
-, props()
-{
-    const Scope& sc = GetRequiredScope(element);
-
-    const std::string& classname = ParseTokenAsString(GetRequiredToken(element,2));
-
-    // hack on the deriving type but Null/LimbNode attributes are the only case in which
-    // the property table is by design absent and no warning should be generated
-    // for it.
-    const bool is_null_or_limb = !strcmp(classname.c_str(), "Null") || !strcmp(classname.c_str(), "LimbNode");
-    props = GetPropertyTable(doc,"NodeAttribute.Fbx" + classname,element,sc, is_null_or_limb);
-}
-
-
-// ------------------------------------------------------------------------------------------------
-NodeAttribute::~NodeAttribute()
-{
-    // empty
-}
-
-
-// ------------------------------------------------------------------------------------------------
-CameraSwitcher::CameraSwitcher(uint64_t id, const Element& element, const Document& doc, const std::string& name)
-    : NodeAttribute(id,element,doc,name)
-{
-    const Scope& sc = GetRequiredScope(element);
-    const Element* const CameraId = sc["CameraId"];
-    const Element* const CameraName = sc["CameraName"];
-    const Element* const CameraIndexName = sc["CameraIndexName"];
-
-    if(CameraId) {
-        cameraId = ParseTokenAsInt(GetRequiredToken(*CameraId,0));
-    }
-
-    if(CameraName) {
-        cameraName = GetRequiredToken(*CameraName,0).StringContents();
-    }
-
-    if(CameraIndexName && CameraIndexName->Tokens().size()) {
-        cameraIndexName = GetRequiredToken(*CameraIndexName,0).StringContents();
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-CameraSwitcher::~CameraSwitcher()
-{
-    // empty
-}
-
-// ------------------------------------------------------------------------------------------------
-Camera::Camera(uint64_t id, const Element& element, const Document& doc, const std::string& name)
-: NodeAttribute(id,element,doc,name)
-{
-    // empty
-}
-
-// ------------------------------------------------------------------------------------------------
-Camera::~Camera()
-{
-    // empty
-}
-
-// ------------------------------------------------------------------------------------------------
-Light::Light(uint64_t id, const Element& element, const Document& doc, const std::string& name)
-: NodeAttribute(id,element,doc,name)
-{
-    // empty
-}
-
-
-// ------------------------------------------------------------------------------------------------
-Light::~Light()
-{
-}
-
-
-// ------------------------------------------------------------------------------------------------
-Null::Null(uint64_t id, const Element& element, const Document& doc, const std::string& name)
-: NodeAttribute(id,element,doc,name)
-{
-
-}
-
-
-// ------------------------------------------------------------------------------------------------
-Null::~Null()
-{
-
-}
-
-
-// ------------------------------------------------------------------------------------------------
-LimbNode::LimbNode(uint64_t id, const Element& element, const Document& doc, const std::string& name)
-: NodeAttribute(id,element,doc,name)
-{
-
-}
-
-
-// ------------------------------------------------------------------------------------------------
-LimbNode::~LimbNode()
-{
-
-}
-
-}
-}
-
-#endif

+ 0 - 1309
thirdparty/assimp/code/FBX/FBXParser.cpp

@@ -1,1309 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file  FBXParser.cpp
- *  @brief Implementation of the FBX parser and the rudimentary DOM that we use
- */
-
-#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
-
-#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
-#   include <zlib.h>
-#else
-#   include "../contrib/zlib/zlib.h"
-#endif
-
-#include "FBXTokenizer.h"
-#include "FBXParser.h"
-#include "FBXUtil.h"
-
-#include <assimp/ParsingUtils.h>
-#include <assimp/fast_atof.h>
-#include <assimp/ByteSwapper.h>
-
-#include <iostream>
-
-using namespace Assimp;
-using namespace Assimp::FBX;
-
-namespace {
-
-    // ------------------------------------------------------------------------------------------------
-    // signal parse error, this is always unrecoverable. Throws DeadlyImportError.
-    AI_WONT_RETURN void ParseError(const std::string& message, const Token& token) AI_WONT_RETURN_SUFFIX;
-    AI_WONT_RETURN void ParseError(const std::string& message, const Token& token)
-    {
-        throw DeadlyImportError(Util::AddTokenText("FBX-Parser",message,&token));
-    }
-
-    // ------------------------------------------------------------------------------------------------
-    AI_WONT_RETURN void ParseError(const std::string& message, const Element* element = NULL) AI_WONT_RETURN_SUFFIX;
-    AI_WONT_RETURN void ParseError(const std::string& message, const Element* element)
-    {
-        if(element) {
-            ParseError(message,element->KeyToken());
-        }
-        throw DeadlyImportError("FBX-Parser " + message);
-    }
-
-
-    // ------------------------------------------------------------------------------------------------
-    void ParseError(const std::string& message, TokenPtr token)
-    {
-        if(token) {
-            ParseError(message, *token);
-        }
-        ParseError(message);
-    }
-
-    // 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
-    template <typename T>
-    T SafeParse(const char* data, const char* end) {
-        // Actual size validation happens during Tokenization so
-        // this is valid as an assertion.
-        (void)(end);
-        ai_assert(static_cast<size_t>(end - data) >= sizeof(T));
-        T result = static_cast<T>(0);
-        ::memcpy(&result, data, sizeof(T));
-        return result;
-    }
-}
-
-namespace Assimp {
-namespace FBX {
-
-// ------------------------------------------------------------------------------------------------
-Element::Element(const Token& key_token, Parser& parser)
-: key_token(key_token)
-{
-    TokenPtr n = nullptr;
-    do {
-        n = parser.AdvanceToNextToken();
-        if(!n) {
-            ParseError("unexpected end of file, expected closing bracket",parser.LastToken());
-        }
-
-        if (n->Type() == TokenType_DATA) {
-            tokens.push_back(n);
-			TokenPtr prev = n;
-            n = parser.AdvanceToNextToken();
-            if(!n) {
-                ParseError("unexpected end of file, expected bracket, comma or key",parser.LastToken());
-            }
-
-			const TokenType ty = n->Type();
-
-			// some exporters are missing a comma on the next line
-			if (ty == TokenType_DATA && prev->Type() == TokenType_DATA && (n->Line() == prev->Line() + 1)) {
-				tokens.push_back(n);
-				continue;
-			}
-
-            if (ty != TokenType_OPEN_BRACKET && ty != TokenType_CLOSE_BRACKET && ty != TokenType_COMMA && ty != TokenType_KEY) {
-                ParseError("unexpected token; expected bracket, comma or key",n);
-            }
-        }
-
-        if (n->Type() == TokenType_OPEN_BRACKET) {
-            compound.reset(new Scope(parser));
-
-            // current token should be a TOK_CLOSE_BRACKET
-            n = parser.CurrentToken();
-            ai_assert(n);
-
-            if (n->Type() != TokenType_CLOSE_BRACKET) {
-                ParseError("expected closing bracket",n);
-            }
-
-            parser.AdvanceToNextToken();
-            return;
-        }
-    }
-    while(n->Type() != TokenType_KEY && n->Type() != TokenType_CLOSE_BRACKET);
-}
-
-// ------------------------------------------------------------------------------------------------
-Element::~Element()
-{
-     // no need to delete tokens, they are owned by the parser
-}
-
-// ------------------------------------------------------------------------------------------------
-Scope::Scope(Parser& parser,bool topLevel)
-{
-    if(!topLevel) {
-        TokenPtr t = parser.CurrentToken();
-        if (t->Type() != TokenType_OPEN_BRACKET) {
-            ParseError("expected open bracket",t);
-        }
-    }
-
-    TokenPtr n = parser.AdvanceToNextToken();
-    if(n == NULL) {
-        ParseError("unexpected end of file");
-    }
-
-    // note: empty scopes are allowed
-    while(n->Type() != TokenType_CLOSE_BRACKET) {
-        if (n->Type() != TokenType_KEY) {
-            ParseError("unexpected token, expected TOK_KEY",n);
-        }
-
-        const std::string& str = n->StringContents();
-        elements.insert(ElementMap::value_type(str,new_Element(*n,parser)));
-
-        // Element() should stop at the next Key token (or right after a Close token)
-        n = parser.CurrentToken();
-        if(n == NULL) {
-            if (topLevel) {
-                return;
-            }
-            ParseError("unexpected end of file",parser.LastToken());
-        }
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-Scope::~Scope()
-{
-    for(ElementMap::value_type& v : elements) {
-        delete v.second;
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-Parser::Parser (const TokenList& tokens, bool is_binary)
-: tokens(tokens)
-, last()
-, current()
-, cursor(tokens.begin())
-, is_binary(is_binary)
-{
-    root.reset(new Scope(*this,true));
-}
-
-// ------------------------------------------------------------------------------------------------
-Parser::~Parser()
-{
-    // empty
-}
-
-// ------------------------------------------------------------------------------------------------
-TokenPtr Parser::AdvanceToNextToken()
-{
-    last = current;
-    if (cursor == tokens.end()) {
-        current = NULL;
-    } else {
-        current = *cursor++;
-    }
-    return current;
-}
-
-// ------------------------------------------------------------------------------------------------
-TokenPtr Parser::CurrentToken() const
-{
-    return current;
-}
-
-// ------------------------------------------------------------------------------------------------
-TokenPtr Parser::LastToken() const
-{
-    return last;
-}
-
-// ------------------------------------------------------------------------------------------------
-uint64_t ParseTokenAsID(const Token& t, const char*& err_out)
-{
-    err_out = NULL;
-
-    if (t.Type() != TokenType_DATA) {
-        err_out = "expected TOK_DATA token";
-        return 0L;
-    }
-
-    if(t.IsBinary())
-    {
-        const char* data = t.begin();
-        if (data[0] != 'L') {
-            err_out = "failed to parse ID, unexpected data type, expected L(ong) (binary)";
-            return 0L;
-        }
-
-        BE_NCONST uint64_t id = SafeParse<uint64_t>(data+1, t.end());
-        AI_SWAP8(id);
-        return id;
-    }
-
-    // XXX: should use size_t here
-    unsigned int length = static_cast<unsigned int>(t.end() - t.begin());
-    ai_assert(length > 0);
-
-    const char* out = nullptr;
-    const uint64_t id = strtoul10_64(t.begin(),&out,&length);
-    if (out > t.end()) {
-        err_out = "failed to parse ID (text)";
-        return 0L;
-    }
-
-    return id;
-}
-
-// ------------------------------------------------------------------------------------------------
-size_t ParseTokenAsDim(const Token& t, const char*& err_out)
-{
-    // same as ID parsing, except there is a trailing asterisk
-    err_out = NULL;
-
-    if (t.Type() != TokenType_DATA) {
-        err_out = "expected TOK_DATA token";
-        return 0;
-    }
-
-    if(t.IsBinary())
-    {
-        const char* data = t.begin();
-        if (data[0] != 'L') {
-            err_out = "failed to parse ID, unexpected data type, expected L(ong) (binary)";
-            return 0;
-        }
-
-        BE_NCONST uint64_t id = SafeParse<uint64_t>(data+1, t.end());
-        AI_SWAP8(id);
-        return static_cast<size_t>(id);
-    }
-
-    if(*t.begin() != '*') {
-        err_out = "expected asterisk before array dimension";
-        return 0;
-    }
-
-    // XXX: should use size_t here
-    unsigned int length = static_cast<unsigned int>(t.end() - t.begin());
-    if(length == 0) {
-        err_out = "expected valid integer number after asterisk";
-        return 0;
-    }
-
-    const char* out = nullptr;
-    const size_t id = static_cast<size_t>(strtoul10_64(t.begin() + 1,&out,&length));
-    if (out > t.end()) {
-        err_out = "failed to parse ID";
-        return 0;
-    }
-
-    return id;
-}
-
-
-// ------------------------------------------------------------------------------------------------
-float ParseTokenAsFloat(const Token& t, const char*& err_out)
-{
-    err_out = NULL;
-
-    if (t.Type() != TokenType_DATA) {
-        err_out = "expected TOK_DATA token";
-        return 0.0f;
-    }
-
-    if(t.IsBinary())
-    {
-        const char* data = t.begin();
-        if (data[0] != 'F' && data[0] != 'D') {
-            err_out = "failed to parse F(loat) or D(ouble), unexpected data type (binary)";
-            return 0.0f;
-        }
-
-        if (data[0] == 'F') {
-            return SafeParse<float>(data+1, t.end());
-        }
-        else {
-            return static_cast<float>( SafeParse<double>(data+1, t.end()) );
-        }
-    }
-
-    // need to copy the input string to a temporary buffer
-    // first - next in the fbx token stream comes ',',
-    // which fast_atof could interpret as decimal point.
-#define MAX_FLOAT_LENGTH 31
-    char temp[MAX_FLOAT_LENGTH + 1];
-    const size_t length = static_cast<size_t>(t.end()-t.begin());
-    std::copy(t.begin(),t.end(),temp);
-    temp[std::min(static_cast<size_t>(MAX_FLOAT_LENGTH),length)] = '\0';
-
-    return fast_atof(temp);
-}
-
-
-// ------------------------------------------------------------------------------------------------
-int ParseTokenAsInt(const Token& t, const char*& err_out)
-{
-    err_out = NULL;
-
-    if (t.Type() != TokenType_DATA) {
-        err_out = "expected TOK_DATA token";
-        return 0;
-    }
-
-    if(t.IsBinary())
-    {
-        const char* data = t.begin();
-        if (data[0] != 'I') {
-            err_out = "failed to parse I(nt), unexpected data type (binary)";
-            return 0;
-        }
-
-        BE_NCONST int32_t ival = SafeParse<int32_t>(data+1, t.end());
-        AI_SWAP4(ival);
-        return static_cast<int>(ival);
-    }
-
-    ai_assert(static_cast<size_t>(t.end() - t.begin()) > 0);
-
-    const char* out;
-    const int intval = strtol10(t.begin(),&out);
-    if (out != t.end()) {
-        err_out = "failed to parse ID";
-        return 0;
-    }
-
-    return intval;
-}
-
-
-// ------------------------------------------------------------------------------------------------
-int64_t ParseTokenAsInt64(const Token& t, const char*& err_out)
-{
-    err_out = NULL;
-
-    if (t.Type() != TokenType_DATA) {
-        err_out = "expected TOK_DATA token";
-        return 0L;
-    }
-
-    if (t.IsBinary())
-    {
-        const char* data = t.begin();
-        if (data[0] != 'L') {
-            err_out = "failed to parse Int64, unexpected data type";
-            return 0L;
-        }
-
-        BE_NCONST int64_t id = SafeParse<int64_t>(data + 1, t.end());
-        AI_SWAP8(id);
-        return id;
-    }
-
-    // XXX: should use size_t here
-    unsigned int length = static_cast<unsigned int>(t.end() - t.begin());
-    ai_assert(length > 0);
-
-    const char* out = nullptr;
-    const int64_t id = strtol10_64(t.begin(), &out, &length);
-    if (out > t.end()) {
-        err_out = "failed to parse Int64 (text)";
-        return 0L;
-    }
-
-    return id;
-}
-
-// ------------------------------------------------------------------------------------------------
-std::string ParseTokenAsString(const Token& t, const char*& err_out)
-{
-    err_out = NULL;
-
-    if (t.Type() != TokenType_DATA) {
-        err_out = "expected TOK_DATA token";
-        return "";
-    }
-
-    if(t.IsBinary())
-    {
-        const char* data = t.begin();
-        if (data[0] != 'S') {
-            err_out = "failed to parse S(tring), unexpected data type (binary)";
-            return "";
-        }
-
-        // read string length
-        BE_NCONST int32_t len = SafeParse<int32_t>(data+1, t.end());
-        AI_SWAP4(len);
-
-        ai_assert(t.end() - data == 5 + len);
-        return std::string(data + 5, len);
-    }
-
-    const size_t length = static_cast<size_t>(t.end() - t.begin());
-    if(length < 2) {
-        err_out = "token is too short to hold a string";
-        return "";
-    }
-
-    const char* s = t.begin(), *e = t.end() - 1;
-    if (*s != '\"' || *e != '\"') {
-        err_out = "expected double quoted string";
-        return "";
-    }
-
-    return std::string(s+1,length-2);
-}
-
-
-namespace {
-
-// ------------------------------------------------------------------------------------------------
-// read the type code and element count of a binary data array and stop there
-void ReadBinaryDataArrayHead(const char*& data, const char* end, char& type, uint32_t& count,
-    const Element& el)
-{
-    if (static_cast<size_t>(end-data) < 5) {
-        ParseError("binary data array is too short, need five (5) bytes for type signature and element count",&el);
-    }
-
-    // data type
-    type = *data;
-
-    // read number of elements
-    BE_NCONST uint32_t len = SafeParse<uint32_t>(data+1, end);
-    AI_SWAP4(len);
-
-    count = len;
-    data += 5;
-}
-
-
-// ------------------------------------------------------------------------------------------------
-// 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*/)
-{
-    BE_NCONST uint32_t encmode = SafeParse<uint32_t>(data, end);
-    AI_SWAP4(encmode);
-    data += 4;
-
-    // next comes the compressed length
-    BE_NCONST uint32_t comp_len = SafeParse<uint32_t>(data, end);
-    AI_SWAP4(comp_len);
-    data += 4;
-
-    ai_assert(data + comp_len == end);
-
-    // determine the length of the uncompressed data by looking at the type signature
-    uint32_t stride = 0;
-    switch(type)
-    {
-        case 'f':
-        case 'i':
-            stride = 4;
-            break;
-
-        case 'd':
-        case 'l':
-            stride = 8;
-            break;
-
-        default:
-            ai_assert(false);
-    };
-
-    const uint32_t full_length = stride * count;
-    buff.resize(full_length);
-
-    if(encmode == 0) {
-        ai_assert(full_length == comp_len);
-
-        // plain data, no compression
-        std::copy(data, end, buff.begin());
-    }
-    else if(encmode == 1) {
-        // zlib/deflate, next comes ZIP head (0x78 0x01)
-        // see http://www.ietf.org/rfc/rfc1950.txt
-
-        z_stream zstream;
-        zstream.opaque = Z_NULL;
-        zstream.zalloc = Z_NULL;
-        zstream.zfree  = Z_NULL;
-        zstream.data_type = Z_BINARY;
-
-        // http://hewgill.com/journal/entries/349-how-to-decompress-gzip-stream-with-zlib
-        if(Z_OK != inflateInit(&zstream)) {
-            ParseError("failure initializing zlib");
-        }
-
-        zstream.next_in   = reinterpret_cast<Bytef*>( const_cast<char*>(data) );
-        zstream.avail_in  = comp_len;
-
-        zstream.avail_out = static_cast<uInt>(buff.size());
-        zstream.next_out = reinterpret_cast<Bytef*>(&*buff.begin());
-        const int ret = inflate(&zstream, Z_FINISH);
-
-        if (ret != Z_STREAM_END && ret != Z_OK) {
-            ParseError("failure decompressing compressed data section");
-        }
-
-        // terminate zlib
-        inflateEnd(&zstream);
-    }
-#ifdef ASSIMP_BUILD_DEBUG
-    else {
-        // runtime check for this happens at tokenization stage
-        ai_assert(false);
-    }
-#endif
-
-    data += comp_len;
-    ai_assert(data == end);
-}
-
-} // !anon
-
-
-// ------------------------------------------------------------------------------------------------
-// read an array of float3 tuples
-void ParseVectorDataArray(std::vector<aiVector3D>& out, const Element& el)
-{
-    out.resize( 0 );
-
-    const TokenList& tok = el.Tokens();
-    if(tok.empty()) {
-        ParseError("unexpected empty element",&el);
-    }
-
-    if(tok[0]->IsBinary()) {
-        const char* data = tok[0]->begin(), *end = tok[0]->end();
-
-        char type;
-        uint32_t count;
-        ReadBinaryDataArrayHead(data, end, type, count, el);
-
-        if(count % 3 != 0) {
-            ParseError("number of floats is not a multiple of three (3) (binary)",&el);
-        }
-
-        if(!count) {
-            return;
-        }
-
-        if (type != 'd' && type != 'f') {
-            ParseError("expected float or double array (binary)",&el);
-        }
-
-        std::vector<char> buff;
-        ReadBinaryDataArray(type, count, data, end, buff, el);
-
-        ai_assert(data == end);
-        ai_assert(buff.size() == count * (type == 'd' ? 8 : 4));
-
-        const uint32_t count3 = count / 3;
-        out.reserve(count3);
-
-        if (type == 'd') {
-            const double* d = reinterpret_cast<const double*>(&buff[0]);
-            for (unsigned int i = 0; i < count3; ++i, d += 3) {
-                out.push_back(aiVector3D(static_cast<ai_real>(d[0]),
-                    static_cast<ai_real>(d[1]),
-                    static_cast<ai_real>(d[2])));
-            }
-            // for debugging
-            /*for ( size_t i = 0; i < out.size(); i++ ) {
-                aiVector3D vec3( out[ i ] );
-                std::stringstream stream;
-                stream << " vec3.x = " << vec3.x << " vec3.y = " << vec3.y << " vec3.z = " << vec3.z << std::endl;
-                DefaultLogger::get()->info( stream.str() );
-            }*/
-        }
-        else if (type == 'f') {
-            const float* f = reinterpret_cast<const float*>(&buff[0]);
-            for (unsigned int i = 0; i < count3; ++i, f += 3) {
-                out.push_back(aiVector3D(f[0],f[1],f[2]));
-            }
-        }
-
-        return;
-    }
-
-    const size_t dim = ParseTokenAsDim(*tok[0]);
-
-    // may throw bad_alloc if the input is rubbish, but this need
-    // not to be prevented - importing would fail but we wouldn't
-    // crash since assimp handles this case properly.
-    out.reserve(dim);
-
-    const Scope& scope = GetRequiredScope(el);
-    const Element& a = GetRequiredElement(scope,"a",&el);
-
-    if (a.Tokens().size() % 3 != 0) {
-        ParseError("number of floats is not a multiple of three (3)",&el);
-    }
-    for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) {
-        aiVector3D v;
-        v.x = ParseTokenAsFloat(**it++);
-        v.y = ParseTokenAsFloat(**it++);
-        v.z = ParseTokenAsFloat(**it++);
-
-        out.push_back(v);
-    }
-}
-
-
-// ------------------------------------------------------------------------------------------------
-// read an array of color4 tuples
-void ParseVectorDataArray(std::vector<aiColor4D>& out, const Element& el)
-{
-    out.resize( 0 );
-    const TokenList& tok = el.Tokens();
-    if(tok.empty()) {
-        ParseError("unexpected empty element",&el);
-    }
-
-    if(tok[0]->IsBinary()) {
-        const char* data = tok[0]->begin(), *end = tok[0]->end();
-
-        char type;
-        uint32_t count;
-        ReadBinaryDataArrayHead(data, end, type, count, el);
-
-        if(count % 4 != 0) {
-            ParseError("number of floats is not a multiple of four (4) (binary)",&el);
-        }
-
-        if(!count) {
-            return;
-        }
-
-        if (type != 'd' && type != 'f') {
-            ParseError("expected float or double array (binary)",&el);
-        }
-
-        std::vector<char> buff;
-        ReadBinaryDataArray(type, count, data, end, buff, el);
-
-        ai_assert(data == end);
-        ai_assert(buff.size() == count * (type == 'd' ? 8 : 4));
-
-        const uint32_t count4 = count / 4;
-        out.reserve(count4);
-
-        if (type == 'd') {
-            const double* d = reinterpret_cast<const double*>(&buff[0]);
-            for (unsigned int i = 0; i < count4; ++i, d += 4) {
-                out.push_back(aiColor4D(static_cast<float>(d[0]),
-                    static_cast<float>(d[1]),
-                    static_cast<float>(d[2]),
-                    static_cast<float>(d[3])));
-            }
-        }
-        else if (type == 'f') {
-            const float* f = reinterpret_cast<const float*>(&buff[0]);
-            for (unsigned int i = 0; i < count4; ++i, f += 4) {
-                out.push_back(aiColor4D(f[0],f[1],f[2],f[3]));
-            }
-        }
-        return;
-    }
-
-    const size_t dim = ParseTokenAsDim(*tok[0]);
-
-    //  see notes in ParseVectorDataArray() above
-    out.reserve(dim);
-
-    const Scope& scope = GetRequiredScope(el);
-    const Element& a = GetRequiredElement(scope,"a",&el);
-
-    if (a.Tokens().size() % 4 != 0) {
-        ParseError("number of floats is not a multiple of four (4)",&el);
-    }
-    for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) {
-        aiColor4D v;
-        v.r = ParseTokenAsFloat(**it++);
-        v.g = ParseTokenAsFloat(**it++);
-        v.b = ParseTokenAsFloat(**it++);
-        v.a = ParseTokenAsFloat(**it++);
-
-        out.push_back(v);
-    }
-}
-
-
-// ------------------------------------------------------------------------------------------------
-// read an array of float2 tuples
-void ParseVectorDataArray(std::vector<aiVector2D>& out, const Element& el)
-{
-    out.resize( 0 );
-    const TokenList& tok = el.Tokens();
-    if(tok.empty()) {
-        ParseError("unexpected empty element",&el);
-    }
-
-    if(tok[0]->IsBinary()) {
-        const char* data = tok[0]->begin(), *end = tok[0]->end();
-
-        char type;
-        uint32_t count;
-        ReadBinaryDataArrayHead(data, end, type, count, el);
-
-        if(count % 2 != 0) {
-            ParseError("number of floats is not a multiple of two (2) (binary)",&el);
-        }
-
-        if(!count) {
-            return;
-        }
-
-        if (type != 'd' && type != 'f') {
-            ParseError("expected float or double array (binary)",&el);
-        }
-
-        std::vector<char> buff;
-        ReadBinaryDataArray(type, count, data, end, buff, el);
-
-        ai_assert(data == end);
-        ai_assert(buff.size() == count * (type == 'd' ? 8 : 4));
-
-        const uint32_t count2 = count / 2;
-        out.reserve(count2);
-
-        if (type == 'd') {
-            const double* d = reinterpret_cast<const double*>(&buff[0]);
-            for (unsigned int i = 0; i < count2; ++i, d += 2) {
-                out.push_back(aiVector2D(static_cast<float>(d[0]),
-                    static_cast<float>(d[1])));
-            }
-        }
-        else if (type == 'f') {
-            const float* f = reinterpret_cast<const float*>(&buff[0]);
-            for (unsigned int i = 0; i < count2; ++i, f += 2) {
-                out.push_back(aiVector2D(f[0],f[1]));
-            }
-        }
-
-        return;
-    }
-
-    const size_t dim = ParseTokenAsDim(*tok[0]);
-
-    // see notes in ParseVectorDataArray() above
-    out.reserve(dim);
-
-    const Scope& scope = GetRequiredScope(el);
-    const Element& a = GetRequiredElement(scope,"a",&el);
-
-    if (a.Tokens().size() % 2 != 0) {
-        ParseError("number of floats is not a multiple of two (2)",&el);
-    }
-    for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) {
-        aiVector2D v;
-        v.x = ParseTokenAsFloat(**it++);
-        v.y = ParseTokenAsFloat(**it++);
-
-        out.push_back(v);
-    }
-}
-
-
-// ------------------------------------------------------------------------------------------------
-// read an array of ints
-void ParseVectorDataArray(std::vector<int>& out, const Element& el)
-{
-    out.resize( 0 );
-    const TokenList& tok = el.Tokens();
-    if(tok.empty()) {
-        ParseError("unexpected empty element",&el);
-    }
-
-    if(tok[0]->IsBinary()) {
-        const char* data = tok[0]->begin(), *end = tok[0]->end();
-
-        char type;
-        uint32_t count;
-        ReadBinaryDataArrayHead(data, end, type, count, el);
-
-        if(!count) {
-            return;
-        }
-
-        if (type != 'i') {
-            ParseError("expected int array (binary)",&el);
-        }
-
-        std::vector<char> buff;
-        ReadBinaryDataArray(type, count, data, end, buff, el);
-
-        ai_assert(data == end);
-        ai_assert(buff.size() == count * 4);
-
-        out.reserve(count);
-
-        const int32_t* ip = reinterpret_cast<const int32_t*>(&buff[0]);
-        for (unsigned int i = 0; i < count; ++i, ++ip) {
-            BE_NCONST int32_t val = *ip;
-            AI_SWAP4(val);
-            out.push_back(val);
-        }
-
-        return;
-    }
-
-    const size_t dim = ParseTokenAsDim(*tok[0]);
-
-    // see notes in ParseVectorDataArray()
-    out.reserve(dim);
-
-    const Scope& scope = GetRequiredScope(el);
-    const Element& a = GetRequiredElement(scope,"a",&el);
-
-    for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) {
-        const int ival = ParseTokenAsInt(**it++);
-        out.push_back(ival);
-    }
-}
-
-
-// ------------------------------------------------------------------------------------------------
-// read an array of floats
-void ParseVectorDataArray(std::vector<float>& out, const Element& el)
-{
-    out.resize( 0 );
-    const TokenList& tok = el.Tokens();
-    if(tok.empty()) {
-        ParseError("unexpected empty element",&el);
-    }
-
-    if(tok[0]->IsBinary()) {
-        const char* data = tok[0]->begin(), *end = tok[0]->end();
-
-        char type;
-        uint32_t count;
-        ReadBinaryDataArrayHead(data, end, type, count, el);
-
-        if(!count) {
-            return;
-        }
-
-        if (type != 'd' && type != 'f') {
-            ParseError("expected float or double array (binary)",&el);
-        }
-
-        std::vector<char> buff;
-        ReadBinaryDataArray(type, count, data, end, buff, el);
-
-        ai_assert(data == end);
-        ai_assert(buff.size() == count * (type == 'd' ? 8 : 4));
-
-        if (type == 'd') {
-            const double* d = reinterpret_cast<const double*>(&buff[0]);
-            for (unsigned int i = 0; i < count; ++i, ++d) {
-                out.push_back(static_cast<float>(*d));
-            }
-        }
-        else if (type == 'f') {
-            const float* f = reinterpret_cast<const float*>(&buff[0]);
-            for (unsigned int i = 0; i < count; ++i, ++f) {
-                out.push_back(*f);
-            }
-        }
-
-        return;
-    }
-
-    const size_t dim = ParseTokenAsDim(*tok[0]);
-
-    // see notes in ParseVectorDataArray()
-    out.reserve(dim);
-
-    const Scope& scope = GetRequiredScope(el);
-    const Element& a = GetRequiredElement(scope,"a",&el);
-
-    for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) {
-        const float ival = ParseTokenAsFloat(**it++);
-        out.push_back(ival);
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-// read an array of uints
-void ParseVectorDataArray(std::vector<unsigned int>& out, const Element& el)
-{
-    out.resize( 0 );
-    const TokenList& tok = el.Tokens();
-    if(tok.empty()) {
-        ParseError("unexpected empty element",&el);
-    }
-
-    if(tok[0]->IsBinary()) {
-        const char* data = tok[0]->begin(), *end = tok[0]->end();
-
-        char type;
-        uint32_t count;
-        ReadBinaryDataArrayHead(data, end, type, count, el);
-
-        if(!count) {
-            return;
-        }
-
-        if (type != 'i') {
-            ParseError("expected (u)int array (binary)",&el);
-        }
-
-        std::vector<char> buff;
-        ReadBinaryDataArray(type, count, data, end, buff, el);
-
-        ai_assert(data == end);
-        ai_assert(buff.size() == count * 4);
-
-        out.reserve(count);
-
-        const int32_t* ip = reinterpret_cast<const int32_t*>(&buff[0]);
-        for (unsigned int i = 0; i < count; ++i, ++ip) {
-            BE_NCONST int32_t val = *ip;
-            if(val < 0) {
-                ParseError("encountered negative integer index (binary)");
-            }
-
-            AI_SWAP4(val);
-            out.push_back(val);
-        }
-
-        return;
-    }
-
-    const size_t dim = ParseTokenAsDim(*tok[0]);
-
-    // see notes in ParseVectorDataArray()
-    out.reserve(dim);
-
-    const Scope& scope = GetRequiredScope(el);
-    const Element& a = GetRequiredElement(scope,"a",&el);
-
-    for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) {
-        const int ival = ParseTokenAsInt(**it++);
-        if(ival < 0) {
-            ParseError("encountered negative integer index");
-        }
-        out.push_back(static_cast<unsigned int>(ival));
-    }
-}
-
-
-// ------------------------------------------------------------------------------------------------
-// read an array of uint64_ts
-void ParseVectorDataArray(std::vector<uint64_t>& out, const Element& el)
-{
-    out.resize( 0 );
-    const TokenList& tok = el.Tokens();
-    if(tok.empty()) {
-        ParseError("unexpected empty element",&el);
-    }
-
-    if(tok[0]->IsBinary()) {
-        const char* data = tok[0]->begin(), *end = tok[0]->end();
-
-        char type;
-        uint32_t count;
-        ReadBinaryDataArrayHead(data, end, type, count, el);
-
-        if(!count) {
-            return;
-        }
-
-        if (type != 'l') {
-            ParseError("expected long array (binary)",&el);
-        }
-
-        std::vector<char> buff;
-        ReadBinaryDataArray(type, count, data, end, buff, el);
-
-        ai_assert(data == end);
-        ai_assert(buff.size() == count * 8);
-
-        out.reserve(count);
-
-        const uint64_t* ip = reinterpret_cast<const uint64_t*>(&buff[0]);
-        for (unsigned int i = 0; i < count; ++i, ++ip) {
-            BE_NCONST uint64_t val = *ip;
-            AI_SWAP8(val);
-            out.push_back(val);
-        }
-
-        return;
-    }
-
-    const size_t dim = ParseTokenAsDim(*tok[0]);
-
-    // see notes in ParseVectorDataArray()
-    out.reserve(dim);
-
-    const Scope& scope = GetRequiredScope(el);
-    const Element& a = GetRequiredElement(scope,"a",&el);
-
-    for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) {
-        const uint64_t ival = ParseTokenAsID(**it++);
-
-        out.push_back(ival);
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-// read an array of int64_ts
-void ParseVectorDataArray(std::vector<int64_t>& out, const Element& el)
-{
-    out.resize( 0 );
-    const TokenList& tok = el.Tokens();
-    if (tok.empty()) {
-        ParseError("unexpected empty element", &el);
-    }
-
-    if (tok[0]->IsBinary()) {
-        const char* data = tok[0]->begin(), *end = tok[0]->end();
-
-        char type;
-        uint32_t count;
-        ReadBinaryDataArrayHead(data, end, type, count, el);
-
-        if (!count) {
-            return;
-        }
-
-        if (type != 'l') {
-            ParseError("expected long array (binary)", &el);
-        }
-
-        std::vector<char> buff;
-        ReadBinaryDataArray(type, count, data, end, buff, el);
-
-        ai_assert(data == end);
-        ai_assert(buff.size() == count * 8);
-
-        out.reserve(count);
-
-        const int64_t* ip = reinterpret_cast<const int64_t*>(&buff[0]);
-        for (unsigned int i = 0; i < count; ++i, ++ip) {
-            BE_NCONST int64_t val = *ip;
-            AI_SWAP8(val);
-            out.push_back(val);
-        }
-
-        return;
-    }
-
-    const size_t dim = ParseTokenAsDim(*tok[0]);
-
-    // see notes in ParseVectorDataArray()
-    out.reserve(dim);
-
-    const Scope& scope = GetRequiredScope(el);
-    const Element& a = GetRequiredElement(scope, "a", &el);
-
-    for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end;) {
-        const int64_t ival = ParseTokenAsInt64(**it++);
-
-        out.push_back(ival);
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-aiMatrix4x4 ReadMatrix(const Element& element)
-{
-    std::vector<float> values;
-    ParseVectorDataArray(values,element);
-
-    if(values.size() != 16) {
-        ParseError("expected 16 matrix elements");
-    }
-
-    aiMatrix4x4 result;
-
-
-    result.a1 = values[0];
-    result.a2 = values[1];
-    result.a3 = values[2];
-    result.a4 = values[3];
-
-    result.b1 = values[4];
-    result.b2 = values[5];
-    result.b3 = values[6];
-    result.b4 = values[7];
-
-    result.c1 = values[8];
-    result.c2 = values[9];
-    result.c3 = values[10];
-    result.c4 = values[11];
-
-    result.d1 = values[12];
-    result.d2 = values[13];
-    result.d3 = values[14];
-    result.d4 = values[15];
-
-    result.Transpose();
-    return result;
-}
-
-
-// ------------------------------------------------------------------------------------------------
-// wrapper around ParseTokenAsString() with ParseError handling
-std::string ParseTokenAsString(const Token& t)
-{
-    const char* err;
-    const std::string& i = ParseTokenAsString(t,err);
-    if(err) {
-        ParseError(err,t);
-    }
-    return i;
-}
-
-bool HasElement( const Scope& sc, const std::string& index ) {
-    const Element* el = sc[ index ];
-    if ( nullptr == el ) {
-        return false;
-    }
-
-    return true;
-}
-
-// ------------------------------------------------------------------------------------------------
-// extract a required element from a scope, abort if the element cannot be found
-const Element& GetRequiredElement(const Scope& sc, const std::string& index, const Element* element /*= NULL*/)
-{
-    const Element* el = sc[index];
-    if(!el) {
-        ParseError("did not find required element \"" + index + "\"",element);
-    }
-    return *el;
-}
-
-
-// ------------------------------------------------------------------------------------------------
-// extract required compound scope
-const Scope& GetRequiredScope(const Element& el)
-{
-    const Scope* const s = el.Compound();
-    if(!s) {
-        ParseError("expected compound scope",&el);
-    }
-
-    return *s;
-}
-
-
-// ------------------------------------------------------------------------------------------------
-// get token at a particular index
-const Token& GetRequiredToken(const Element& el, unsigned int index)
-{
-    const TokenList& t = el.Tokens();
-    if(index >= t.size()) {
-        ParseError(Formatter::format( "missing token at index " ) << index,&el);
-    }
-
-    return *t[index];
-}
-
-
-// ------------------------------------------------------------------------------------------------
-// wrapper around ParseTokenAsID() with ParseError handling
-uint64_t ParseTokenAsID(const Token& t)
-{
-    const char* err;
-    const uint64_t i = ParseTokenAsID(t,err);
-    if(err) {
-        ParseError(err,t);
-    }
-    return i;
-}
-
-
-// ------------------------------------------------------------------------------------------------
-// wrapper around ParseTokenAsDim() with ParseError handling
-size_t ParseTokenAsDim(const Token& t)
-{
-    const char* err;
-    const size_t i = ParseTokenAsDim(t,err);
-    if(err) {
-        ParseError(err,t);
-    }
-    return i;
-}
-
-
-// ------------------------------------------------------------------------------------------------
-// wrapper around ParseTokenAsFloat() with ParseError handling
-float ParseTokenAsFloat(const Token& t)
-{
-    const char* err;
-    const float i = ParseTokenAsFloat(t,err);
-    if(err) {
-        ParseError(err,t);
-    }
-    return i;
-}
-
-// ------------------------------------------------------------------------------------------------
-// wrapper around ParseTokenAsInt() with ParseError handling
-int ParseTokenAsInt(const Token& t)
-{
-    const char* err;
-    const int i = ParseTokenAsInt(t,err);
-    if(err) {
-        ParseError(err,t);
-    }
-    return i;
-}
-
-// ------------------------------------------------------------------------------------------------
-// wrapper around ParseTokenAsInt64() with ParseError handling
-int64_t ParseTokenAsInt64(const Token& t)
-{
-    const char* err;
-    const int64_t i = ParseTokenAsInt64(t, err);
-    if (err) {
-        ParseError(err, t);
-    }
-    return i;
-}
-
-} // !FBX
-} // !Assimp
-
-#endif

+ 0 - 235
thirdparty/assimp/code/FBX/FBXParser.h

@@ -1,235 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file  FBXParser.h
- *  @brief FBX parsing code
- */
-#ifndef INCLUDED_AI_FBX_PARSER_H
-#define INCLUDED_AI_FBX_PARSER_H
-
-#include <stdint.h>
-#include <map>
-#include <memory>
-#include <assimp/LogAux.h>
-#include <assimp/fast_atof.h>
-
-#include "FBXCompileConfig.h"
-#include "FBXTokenizer.h"
-
-namespace Assimp {
-namespace FBX {
-
-class Scope;
-class Parser;
-class Element;
-
-// XXX should use C++11's unique_ptr - but assimp's need to keep working with 03
-typedef std::vector< Scope* > ScopeList;
-typedef std::fbx_unordered_multimap< std::string, Element* > ElementMap;
-
-typedef std::pair<ElementMap::const_iterator,ElementMap::const_iterator> ElementCollection;
-
-#   define new_Scope new Scope
-#   define new_Element new Element
-
-
-/** FBX data entity that consists of a key:value tuple.
- *
- *  Example:
- *  @verbatim
- *    AnimationCurve: 23, "AnimCurve::", "" {
- *        [..]
- *    }
- *  @endverbatim
- *
- *  As can be seen in this sample, elements can contain nested #Scope
- *  as their trailing member.  **/
-class Element
-{
-public:
-    Element(const Token& key_token, Parser& parser);
-    ~Element();
-
-    const Scope* Compound() const {
-        return compound.get();
-    }
-
-    const Token& KeyToken() const {
-        return key_token;
-    }
-
-    const TokenList& Tokens() const {
-        return tokens;
-    }
-
-private:
-    const Token& key_token;
-    TokenList tokens;
-    std::unique_ptr<Scope> compound;
-};
-
-/** FBX data entity that consists of a 'scope', a collection
- *  of not necessarily unique #Element instances.
- *
- *  Example:
- *  @verbatim
- *    GlobalSettings:  {
- *        Version: 1000
- *        Properties70:
- *        [...]
- *    }
- *  @endverbatim  */
-class Scope
-{
-public:
-    Scope(Parser& parser, bool topLevel = false);
-    ~Scope();
-
-    const Element* operator[] (const std::string& index) const {
-        ElementMap::const_iterator it = elements.find(index);
-        return it == elements.end() ? NULL : (*it).second;
-    }
-
-	const Element* FindElementCaseInsensitive(const std::string& elementName) const {
-		const char* elementNameCStr = elementName.c_str();
-		for (auto element = elements.begin(); element != elements.end(); ++element)
-		{
-			if (!ASSIMP_strincmp(element->first.c_str(), elementNameCStr, MAXLEN)) {
-				return element->second;
-			}
-		}
-		return NULL;
-	}
-
-    ElementCollection GetCollection(const std::string& index) const {
-        return elements.equal_range(index);
-    }
-
-    const ElementMap& Elements() const  {
-        return elements;
-    }
-
-private:
-    ElementMap elements;
-};
-
-/** FBX parsing class, takes a list of input tokens and generates a hierarchy
- *  of nested #Scope instances, representing the fbx DOM.*/
-class Parser
-{
-public:
-    /** Parse given a token list. Does not take ownership of the tokens -
-     *  the objects must persist during the entire parser lifetime */
-    Parser (const TokenList& tokens,bool is_binary);
-    ~Parser();
-
-    const Scope& GetRootScope() const {
-        return *root.get();
-    }
-
-    bool IsBinary() const {
-        return is_binary;
-    }
-
-private:
-    friend class Scope;
-    friend class Element;
-
-    TokenPtr AdvanceToNextToken();
-    TokenPtr LastToken() const;
-    TokenPtr CurrentToken() const;
-
-private:
-    const TokenList& tokens;
-
-    TokenPtr last, current;
-    TokenList::const_iterator cursor;
-    std::unique_ptr<Scope> root;
-
-    const bool is_binary;
-};
-
-
-/* token parsing - this happens when building the DOM out of the parse-tree*/
-uint64_t ParseTokenAsID(const Token& t, const char*& err_out);
-size_t ParseTokenAsDim(const Token& t, const char*& err_out);
-
-float ParseTokenAsFloat(const Token& t, const char*& err_out);
-int ParseTokenAsInt(const Token& t, const char*& err_out);
-int64_t ParseTokenAsInt64(const Token& t, const char*& err_out);
-std::string ParseTokenAsString(const Token& t, const char*& err_out);
-
-/* wrapper around ParseTokenAsXXX() with DOMError handling */
-uint64_t ParseTokenAsID(const Token& t);
-size_t ParseTokenAsDim(const Token& t);
-float ParseTokenAsFloat(const Token& t);
-int ParseTokenAsInt(const Token& t);
-int64_t ParseTokenAsInt64(const Token& t);
-std::string ParseTokenAsString(const Token& t);
-
-/* read data arrays */
-void ParseVectorDataArray(std::vector<aiVector3D>& out, const Element& el);
-void ParseVectorDataArray(std::vector<aiColor4D>& out, const Element& el);
-void ParseVectorDataArray(std::vector<aiVector2D>& out, const Element& el);
-void ParseVectorDataArray(std::vector<int>& out, const Element& el);
-void ParseVectorDataArray(std::vector<float>& out, const Element& el);
-void ParseVectorDataArray(std::vector<unsigned int>& out, const Element& el);
-void ParseVectorDataArray(std::vector<uint64_t>& out, const Element& e);
-void ParseVectorDataArray(std::vector<int64_t>& out, const Element& el);
-
-bool HasElement( const Scope& sc, const std::string& index );
-
-// extract a required element from a scope, abort if the element cannot be found
-const Element& GetRequiredElement(const Scope& sc, const std::string& index, const Element* element = NULL);
-
-// extract required compound scope
-const Scope& GetRequiredScope(const Element& el);
-// get token at a particular index
-const Token& GetRequiredToken(const Element& el, unsigned int index);
-
-// read a 4x4 matrix from an array of 16 floats
-aiMatrix4x4 ReadMatrix(const Element& element);
-
-} // ! FBX
-} // ! Assimp
-
-#endif // ! INCLUDED_AI_FBX_PARSER_H

+ 0 - 235
thirdparty/assimp/code/FBX/FBXProperties.cpp

@@ -1,235 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file  FBXProperties.cpp
- *  @brief Implementation of the FBX dynamic properties system
- */
-
-#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
-
-#include "FBXTokenizer.h"
-#include "FBXParser.h"
-#include "FBXDocument.h"
-#include "FBXDocumentUtil.h"
-#include "FBXProperties.h"
-
-namespace Assimp {
-namespace FBX {
-
-    using namespace Util;
-
-// ------------------------------------------------------------------------------------------------
-Property::Property()
-{
-}
-
-// ------------------------------------------------------------------------------------------------
-Property::~Property()
-{
-}
-
-namespace {
-
-// ------------------------------------------------------------------------------------------------
-// read a typed property out of a FBX element. The return value is NULL if the property cannot be read.
-Property* ReadTypedProperty(const Element& element)
-{
-    ai_assert(element.KeyToken().StringContents() == "P");
-
-    const TokenList& tok = element.Tokens();
-    ai_assert(tok.size() >= 5);
-
-    const std::string& s = ParseTokenAsString(*tok[1]);
-    const char* const cs = s.c_str();
-    if (!strcmp(cs,"KString")) {
-        return new TypedProperty<std::string>(ParseTokenAsString(*tok[4]));
-    }
-    else if (!strcmp(cs,"bool") || !strcmp(cs,"Bool")) {
-        return new TypedProperty<bool>(ParseTokenAsInt(*tok[4]) != 0);
-    }
-    else if (!strcmp(cs, "int") || !strcmp(cs, "Int") || !strcmp(cs, "enum") || !strcmp(cs, "Enum")) {
-        return new TypedProperty<int>(ParseTokenAsInt(*tok[4]));
-    }
-    else if (!strcmp(cs, "ULongLong")) {
-        return new TypedProperty<uint64_t>(ParseTokenAsID(*tok[4]));
-    }
-    else if (!strcmp(cs, "KTime")) {
-        return new TypedProperty<int64_t>(ParseTokenAsInt64(*tok[4]));
-    }
-    else if (!strcmp(cs,"Vector3D") ||
-        !strcmp(cs,"ColorRGB") ||
-        !strcmp(cs,"Vector") ||
-        !strcmp(cs,"Color") ||
-        !strcmp(cs,"Lcl Translation") ||
-        !strcmp(cs,"Lcl Rotation") ||
-        !strcmp(cs,"Lcl Scaling")
-        ) {
-        return new TypedProperty<aiVector3D>(aiVector3D(
-            ParseTokenAsFloat(*tok[4]),
-            ParseTokenAsFloat(*tok[5]),
-            ParseTokenAsFloat(*tok[6]))
-        );
-    }
-    else if (!strcmp(cs,"double") || !strcmp(cs,"Number") || !strcmp(cs,"Float") || !strcmp(cs,"FieldOfView") || !strcmp( cs, "UnitScaleFactor" ) ) {
-        return new TypedProperty<float>(ParseTokenAsFloat(*tok[4]));
-    }
-    return NULL;
-}
-
-
-// ------------------------------------------------------------------------------------------------
-// peek into an element and check if it contains a FBX property, if so return its name.
-std::string PeekPropertyName(const Element& element)
-{
-    ai_assert(element.KeyToken().StringContents() == "P");
-    const TokenList& tok = element.Tokens();
-    if(tok.size() < 4) {
-        return "";
-    }
-
-    return ParseTokenAsString(*tok[0]);
-}
-
-} //! anon
-
-
-// ------------------------------------------------------------------------------------------------
-PropertyTable::PropertyTable()
-: templateProps()
-, element()
-{
-}
-
-// ------------------------------------------------------------------------------------------------
-PropertyTable::PropertyTable(const Element& element, std::shared_ptr<const PropertyTable> templateProps)
-: templateProps(templateProps)
-, element(&element)
-{
-    const Scope& scope = GetRequiredScope(element);
-    for(const ElementMap::value_type& v : scope.Elements()) {
-        if(v.first != "P") {
-            DOMWarning("expected only P elements in property table",v.second);
-            continue;
-        }
-
-        const std::string& name = PeekPropertyName(*v.second);
-        if(!name.length()) {
-            DOMWarning("could not read property name",v.second);
-            continue;
-        }
-
-        LazyPropertyMap::const_iterator it = lazyProps.find(name);
-        if (it != lazyProps.end()) {
-            DOMWarning("duplicate property name, will hide previous value: " + name,v.second);
-            continue;
-        }
-
-        lazyProps[name] = v.second;
-    }
-}
-
-
-// ------------------------------------------------------------------------------------------------
-PropertyTable::~PropertyTable()
-{
-    for(PropertyMap::value_type& v : props) {
-        delete v.second;
-    }
-}
-
-
-// ------------------------------------------------------------------------------------------------
-const Property* PropertyTable::Get(const std::string& name) const
-{
-    PropertyMap::const_iterator it = props.find(name);
-    if (it == props.end()) {
-        // hasn't been parsed yet?
-        LazyPropertyMap::const_iterator lit = lazyProps.find(name);
-        if(lit != lazyProps.end()) {
-            props[name] = ReadTypedProperty(*(*lit).second);
-            it = props.find(name);
-
-            ai_assert(it != props.end());
-        }
-
-        if (it == props.end()) {
-            // check property template
-            if(templateProps) {
-                return templateProps->Get(name);
-            }
-
-            return NULL;
-        }
-    }
-
-    return (*it).second;
-}
-
-DirectPropertyMap PropertyTable::GetUnparsedProperties() const
-{
-    DirectPropertyMap result;
-
-    // Loop through all the lazy properties (which is all the properties)
-    for(const LazyPropertyMap::value_type& element : lazyProps) {
-
-        // Skip parsed properties
-        if (props.end() != props.find(element.first)) continue;
-
-        // Read the element's value.
-        // Wrap the naked pointer (since the call site is required to acquire ownership)
-        // std::unique_ptr from C++11 would be preferred both as a wrapper and a return value.
-        std::shared_ptr<Property> prop = std::shared_ptr<Property>(ReadTypedProperty(*element.second));
-
-        // Element could not be read. Skip it.
-        if (!prop) continue;
-
-        // Add to result
-        result[element.first] = prop;
-    }
-
-    return result;
-}
-
-} //! FBX
-} //! Assimp
-
-#endif

+ 0 - 185
thirdparty/assimp/code/FBX/FBXProperties.h

@@ -1,185 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file  FBXProperties.h
- *  @brief FBX dynamic properties
- */
-#ifndef INCLUDED_AI_FBX_PROPERTIES_H
-#define INCLUDED_AI_FBX_PROPERTIES_H
-
-#include "FBXCompileConfig.h"
-#include <memory>
-#include <string>
-
-namespace Assimp {
-namespace FBX {
-
-// Forward declarations
-class Element;
-
-/** Represents a dynamic property. Type info added by deriving classes,
- *  see #TypedProperty.
- Example:
- @verbatim
-   P: "ShininessExponent", "double", "Number", "",0.5
- @endvebatim
-*/
-class Property {
-protected:
-    Property();
-
-public:
-    virtual ~Property();
-
-public:
-    template <typename T>
-    const T* As() const {
-        return dynamic_cast<const T*>(this);
-    }
-};
-
-template<typename T>
-class TypedProperty : public Property {
-public:
-    explicit TypedProperty(const T& value)
-    : value(value) {
-        // empty
-    }
-
-    const T& Value() const {
-        return value;
-    }
-
-private:
-    T value;
-};
-
-
-typedef std::fbx_unordered_map<std::string,std::shared_ptr<Property> > DirectPropertyMap;
-typedef std::fbx_unordered_map<std::string,const Property*>            PropertyMap;
-typedef std::fbx_unordered_map<std::string,const Element*>             LazyPropertyMap;
-
-/** 
- *  Represents a property table as can be found in the newer FBX files (Properties60, Properties70)
- */
-class PropertyTable {
-public:
-    // in-memory property table with no source element
-    PropertyTable();
-    PropertyTable(const Element& element, std::shared_ptr<const PropertyTable> templateProps);
-    ~PropertyTable();
-
-    const Property* Get(const std::string& name) const;
-
-    // PropertyTable's need not be coupled with FBX elements so this can be NULL
-    const Element* GetElement() const {
-        return element;
-    }
-
-    const PropertyTable* TemplateProps() const {
-        return templateProps.get();
-    }
-
-    DirectPropertyMap GetUnparsedProperties() const;
-
-private:
-    LazyPropertyMap lazyProps;
-    mutable PropertyMap props;
-    const std::shared_ptr<const PropertyTable> templateProps;
-    const Element* const element;
-};
-
-// ------------------------------------------------------------------------------------------------
-template <typename T>
-inline 
-T PropertyGet(const PropertyTable& in, const std::string& name, const T& defaultValue) {
-    const Property* const prop = in.Get(name);
-    if( nullptr == prop) {
-        return defaultValue;
-    }
-
-    // strong typing, no need to be lenient
-    const TypedProperty<T>* const tprop = prop->As< TypedProperty<T> >();
-    if( nullptr == tprop) {
-        return defaultValue;
-    }
-
-    return tprop->Value();
-}
-
-// ------------------------------------------------------------------------------------------------
-template <typename T>
-inline 
-T PropertyGet(const PropertyTable& in, const std::string& name, bool& result, bool useTemplate=false ) {
-    const Property* prop = in.Get(name);
-    if( nullptr == prop) {
-        if ( ! useTemplate ) {
-            result = false;
-            return T();
-        }
-        const PropertyTable* templ = in.TemplateProps();
-        if ( nullptr == templ ) {
-            result = false;
-            return T();
-        }
-        prop = templ->Get(name);
-        if ( nullptr == prop ) {
-            result = false;
-            return T();
-        }
-    }
-
-    // strong typing, no need to be lenient
-    const TypedProperty<T>* const tprop = prop->As< TypedProperty<T> >();
-    if( nullptr == tprop) {
-        result = false;
-        return T();
-    }
-
-    result = true;
-    return tprop->Value();
-}
-
-} //! FBX
-} //! Assimp
-
-#endif // INCLUDED_AI_FBX_PROPERTIES_H

+ 0 - 248
thirdparty/assimp/code/FBX/FBXTokenizer.cpp

@@ -1,248 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file  FBXTokenizer.cpp
- *  @brief Implementation of the FBX broadphase lexer
- */
-
-#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
-
-// tab width for logging columns
-#define ASSIMP_FBX_TAB_WIDTH 4
-
-#include <assimp/ParsingUtils.h>
-
-#include "FBXTokenizer.h"
-#include "FBXUtil.h"
-#include <assimp/Exceptional.h>
-
-namespace Assimp {
-namespace FBX {
-
-// ------------------------------------------------------------------------------------------------
-Token::Token(const char* sbegin, const char* send, TokenType type, unsigned int line, unsigned int column)
-    :
-#ifdef DEBUG
-    contents(sbegin, static_cast<size_t>(send-sbegin)),
-#endif
-    sbegin(sbegin)
-    , send(send)
-    , type(type)
-    , line(line)
-    , column(column)
-{
-    ai_assert(sbegin);
-    ai_assert(send);
-
-    // tokens must be of non-zero length
-    ai_assert(static_cast<size_t>(send-sbegin) > 0);
-}
-
-// ------------------------------------------------------------------------------------------------
-Token::~Token()
-{
-}
-
-namespace {
-
-// ------------------------------------------------------------------------------------------------
-// signal tokenization error, this is always unrecoverable. Throws DeadlyImportError.
-AI_WONT_RETURN void TokenizeError(const std::string& message, unsigned int line, unsigned int column) AI_WONT_RETURN_SUFFIX;
-AI_WONT_RETURN void TokenizeError(const std::string& message, unsigned int line, unsigned int column)
-{
-    throw DeadlyImportError(Util::AddLineAndColumn("FBX-Tokenize",message,line,column));
-}
-
-
-// process a potential data token up to 'cur', adding it to 'output_tokens'.
-// ------------------------------------------------------------------------------------------------
-void ProcessDataToken( TokenList& output_tokens, const char*& start, const char*& end,
-                      unsigned int line,
-                      unsigned int column,
-                      TokenType type = TokenType_DATA,
-                      bool must_have_token = false)
-{
-    if (start && end) {
-        // sanity check:
-        // tokens should have no whitespace outside quoted text and [start,end] should
-        // properly delimit the valid range.
-        bool in_double_quotes = false;
-        for (const char* c = start; c != end + 1; ++c) {
-            if (*c == '\"') {
-                in_double_quotes = !in_double_quotes;
-            }
-
-            if (!in_double_quotes && IsSpaceOrNewLine(*c)) {
-                TokenizeError("unexpected whitespace in token", line, column);
-            }
-        }
-
-        if (in_double_quotes) {
-            TokenizeError("non-terminated double quotes", line, column);
-        }
-
-        output_tokens.push_back(new_Token(start,end + 1,type,line,column));
-    }
-    else if (must_have_token) {
-        TokenizeError("unexpected character, expected data token", line, column);
-    }
-
-    start = end = NULL;
-}
-
-}
-
-// ------------------------------------------------------------------------------------------------
-void Tokenize(TokenList& output_tokens, const char* input)
-{
-    ai_assert(input);
-
-    // line and column numbers numbers are one-based
-    unsigned int line = 1;
-    unsigned int column = 1;
-
-    bool comment = false;
-    bool in_double_quotes = false;
-    bool pending_data_token = false;
-
-    const char* token_begin = NULL, *token_end = NULL;
-    for (const char* cur = input;*cur;column += (*cur == '\t' ? ASSIMP_FBX_TAB_WIDTH : 1), ++cur) {
-        const char c = *cur;
-
-        if (IsLineEnd(c)) {
-            comment = false;
-
-            column = 0;
-            ++line;
-        }
-
-        if(comment) {
-            continue;
-        }
-
-        if(in_double_quotes) {
-            if (c == '\"') {
-                in_double_quotes = false;
-                token_end = cur;
-
-                ProcessDataToken(output_tokens,token_begin,token_end,line,column);
-                pending_data_token = false;
-            }
-            continue;
-        }
-
-        switch(c)
-        {
-        case '\"':
-            if (token_begin) {
-                TokenizeError("unexpected double-quote", line, column);
-            }
-            token_begin = cur;
-            in_double_quotes = true;
-            continue;
-
-        case ';':
-            ProcessDataToken(output_tokens,token_begin,token_end,line,column);
-            comment = true;
-            continue;
-
-        case '{':
-            ProcessDataToken(output_tokens,token_begin,token_end, line, column);
-            output_tokens.push_back(new_Token(cur,cur+1,TokenType_OPEN_BRACKET,line,column));
-            continue;
-
-        case '}':
-            ProcessDataToken(output_tokens,token_begin,token_end,line,column);
-            output_tokens.push_back(new_Token(cur,cur+1,TokenType_CLOSE_BRACKET,line,column));
-            continue;
-
-        case ',':
-            if (pending_data_token) {
-                ProcessDataToken(output_tokens,token_begin,token_end,line,column,TokenType_DATA,true);
-            }
-            output_tokens.push_back(new_Token(cur,cur+1,TokenType_COMMA,line,column));
-            continue;
-
-        case ':':
-            if (pending_data_token) {
-                ProcessDataToken(output_tokens,token_begin,token_end,line,column,TokenType_KEY,true);
-            }
-            else {
-                TokenizeError("unexpected colon", line, column);
-            }
-            continue;
-        }
-
-        if (IsSpaceOrNewLine(c)) {
-
-            if (token_begin) {
-                // peek ahead and check if the next token is a colon in which
-                // case this counts as KEY token.
-                TokenType type = TokenType_DATA;
-                for (const char* peek = cur;  *peek && IsSpaceOrNewLine(*peek); ++peek) {
-                    if (*peek == ':') {
-                        type = TokenType_KEY;
-                        cur = peek;
-                        break;
-                    }
-                }
-
-                ProcessDataToken(output_tokens,token_begin,token_end,line,column,type);
-            }
-
-            pending_data_token = false;
-        }
-        else {
-            token_end = cur;
-            if (!token_begin) {
-                token_begin = cur;
-            }
-
-            pending_data_token = true;
-        }
-    }
-}
-
-} // !FBX
-} // !Assimp
-
-#endif

+ 0 - 187
thirdparty/assimp/code/FBX/FBXTokenizer.h

@@ -1,187 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file  FBXTokenizer.h
- *  @brief FBX lexer
- */
-#ifndef INCLUDED_AI_FBX_TOKENIZER_H
-#define INCLUDED_AI_FBX_TOKENIZER_H
-
-#include "FBXCompileConfig.h"
-#include <assimp/ai_assert.h>
-#include <vector>
-#include <string>
-
-namespace Assimp {
-namespace FBX {
-
-/** Rough classification for text FBX tokens used for constructing the
- *  basic scope hierarchy. */
-enum TokenType
-{
-    // {
-    TokenType_OPEN_BRACKET = 0,
-
-    // }
-    TokenType_CLOSE_BRACKET,
-
-    // '"blablubb"', '2', '*14' - very general token class,
-    // further processing happens at a later stage.
-    TokenType_DATA,
-
-    //
-    TokenType_BINARY_DATA,
-
-    // ,
-    TokenType_COMMA,
-
-    // blubb:
-    TokenType_KEY
-};
-
-
-/** Represents a single token in a FBX file. Tokens are
- *  classified by the #TokenType enumerated types.
- *
- *  Offers iterator protocol. Tokens are immutable. */
-class Token
-{
-private:
-    static const unsigned int BINARY_MARKER = static_cast<unsigned int>(-1);
-
-public:
-    /** construct a textual token */
-    Token(const char* sbegin, const char* send, TokenType type, unsigned int line, unsigned int column);
-
-    /** construct a binary token */
-    Token(const char* sbegin, const char* send, TokenType type, size_t offset);
-
-    ~Token();
-
-public:
-    std::string StringContents() const {
-        return std::string(begin(),end());
-    }
-
-    bool IsBinary() const {
-        return column == BINARY_MARKER;
-    }
-
-    const char* begin() const {
-        return sbegin;
-    }
-
-    const char* end() const {
-        return send;
-    }
-
-    TokenType Type() const {
-        return type;
-    }
-
-    size_t Offset() const {
-        ai_assert(IsBinary());
-        return offset;
-    }
-
-    unsigned int Line() const {
-        ai_assert(!IsBinary());
-        return static_cast<unsigned int>(line);
-    }
-
-    unsigned int Column() const {
-        ai_assert(!IsBinary());
-        return column;
-    }
-
-private:
-
-#ifdef DEBUG
-    // full string copy for the sole purpose that it nicely appears
-    // in msvc's debugger window.
-    const std::string contents;
-#endif
-
-
-    const char* const sbegin;
-    const char* const send;
-    const TokenType type;
-
-    union {
-        size_t line;
-        size_t offset;
-    };
-    const unsigned int column;
-};
-
-// XXX should use C++11's unique_ptr - but assimp's need to keep working with 03
-typedef const Token* TokenPtr;
-typedef std::vector< TokenPtr > TokenList;
-
-#define new_Token new Token
-
-
-/** Main FBX tokenizer function. Transform input buffer into a list of preprocessed tokens.
- *
- *  Skips over comments and generates line and column numbers.
- *
- * @param output_tokens Receives a list of all tokens in the input data.
- * @param input_buffer Textual input buffer to be processed, 0-terminated.
- * @throw DeadlyImportError if something goes wrong */
-void Tokenize(TokenList& output_tokens, const char* input);
-
-
-/** Tokenizer function for binary FBX files.
- *
- *  Emits a token list suitable for direct parsing.
- *
- * @param output_tokens Receives a list of all tokens in the input data.
- * @param input_buffer Binary input buffer to be processed.
- * @param length Length of input buffer, in bytes. There is no 0-terminal.
- * @throw DeadlyImportError if something goes wrong */
-void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length);
-
-
-} // ! FBX
-} // ! Assimp
-
-#endif // ! INCLUDED_AI_FBX_PARSER_H

+ 0 - 243
thirdparty/assimp/code/FBX/FBXUtil.cpp

@@ -1,243 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file  FBXUtil.cpp
- *  @brief Implementation of internal FBX utility functions
- */
-
-#include "FBXUtil.h"
-#include "FBXTokenizer.h"
-
-#include <assimp/TinyFormatter.h>
-#include <string>
-#include <cstring>
-
-#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
-
-namespace Assimp {
-namespace FBX {
-namespace Util {
-
-// ------------------------------------------------------------------------------------------------
-const char* TokenTypeString(TokenType t)
-{
-    switch(t) {
-        case TokenType_OPEN_BRACKET:
-            return "TOK_OPEN_BRACKET";
-
-        case TokenType_CLOSE_BRACKET:
-            return "TOK_CLOSE_BRACKET";
-
-        case TokenType_DATA:
-            return "TOK_DATA";
-
-        case TokenType_COMMA:
-            return "TOK_COMMA";
-
-        case TokenType_KEY:
-            return "TOK_KEY";
-
-        case TokenType_BINARY_DATA:
-            return "TOK_BINARY_DATA";
-    }
-
-    ai_assert(false);
-    return "";
-}
-
-
-// ------------------------------------------------------------------------------------------------
-std::string AddOffset(const std::string& prefix, const std::string& text, size_t offset)
-{
-    return static_cast<std::string>( (Formatter::format() << prefix << " (offset 0x" << std::hex << offset << ") " << text) );
-}
-
-// ------------------------------------------------------------------------------------------------
-std::string AddLineAndColumn(const std::string& prefix, const std::string& text, unsigned int line, unsigned int column)
-{
-    return static_cast<std::string>( (Formatter::format() << prefix << " (line " << line << " <<  col " << column << ") " << text) );
-}
-
-// ------------------------------------------------------------------------------------------------
-std::string AddTokenText(const std::string& prefix, const std::string& text, const Token* tok)
-{
-    if(tok->IsBinary()) {
-        return static_cast<std::string>( (Formatter::format() << prefix <<
-            " (" << TokenTypeString(tok->Type()) <<
-            ", offset 0x" << std::hex << tok->Offset() << ") " <<
-            text) );
-    }
-
-    return static_cast<std::string>( (Formatter::format() << prefix <<
-        " (" << TokenTypeString(tok->Type()) <<
-        ", line " << tok->Line() <<
-        ", col " << tok->Column() << ") " <<
-        text) );
-}
-
-// Generated by this formula: T["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[i]] = i;
-static const uint8_t base64DecodeTable[128] = {
-    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
-    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 255, 255, 255,
-    255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
-    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,
-    255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
-    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255
-};
-
-uint8_t DecodeBase64(char ch)
-{
-    const auto idx = static_cast<uint8_t>(ch);
-    if (idx > 127)
-        return 255;
-    return base64DecodeTable[idx];
-}
-
-size_t ComputeDecodedSizeBase64(const char* in, size_t inLength)
-{
-    if (inLength < 2)
-    {
-        return 0;
-    }
-    const size_t equals = size_t(in[inLength - 1] == '=') + size_t(in[inLength - 2] == '=');
-    const size_t full_length = (inLength * 3) >> 2; // div by 4
-    if (full_length < equals)
-    {
-        return 0;
-    }
-    return full_length - equals;
-}
-
-size_t DecodeBase64(const char* in, size_t inLength, uint8_t* out, size_t maxOutLength)
-{
-    if (maxOutLength == 0 || inLength < 2) {
-        return 0;
-    }
-    const size_t realLength = inLength - size_t(in[inLength - 1] == '=') - size_t(in[inLength - 2] == '=');
-    size_t dst_offset = 0;
-    int val = 0, valb = -8;
-    for (size_t src_offset = 0; src_offset < realLength; ++src_offset)
-    {
-        const uint8_t table_value = Util::DecodeBase64(in[src_offset]);
-        if (table_value == 255)
-        {
-            return 0;
-        }
-        val = (val << 6) + table_value;
-        valb += 6;
-        if (valb >= 0)
-        {
-            out[dst_offset++] = static_cast<uint8_t>((val >> valb) & 0xFF);
-            valb -= 8;
-            val &= 0xFFF;
-        }
-    }
-    return dst_offset;
-}
-
-static const char to_base64_string[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-char EncodeBase64(char byte)
-{
-    return to_base64_string[(size_t)byte];
-}
-
-/** Encodes a block of 4 bytes to base64 encoding
-*
-*  @param bytes Bytes to encode.
-*  @param out_string String to write encoded values to.
-*  @param string_pos Position in out_string.*/
-void EncodeByteBlock(const char* bytes, std::string& out_string, size_t string_pos)
-{
-    char b0 = (bytes[0] & 0xFC) >> 2;
-    char b1 = (bytes[0] & 0x03) << 4 | ((bytes[1] & 0xF0) >> 4);
-    char b2 = (bytes[1] & 0x0F) << 2 | ((bytes[2] & 0xC0) >> 6);
-    char b3 = (bytes[2] & 0x3F);
-
-    out_string[string_pos + 0] = EncodeBase64(b0);
-    out_string[string_pos + 1] = EncodeBase64(b1);
-    out_string[string_pos + 2] = EncodeBase64(b2);
-    out_string[string_pos + 3] = EncodeBase64(b3);
-}
-
-std::string EncodeBase64(const char* data, size_t length)
-{
-    // calculate extra bytes needed to get a multiple of 3
-    size_t extraBytes = 3 - length % 3;
-
-    // number of base64 bytes
-    size_t encodedBytes = 4 * (length + extraBytes) / 3;
-
-    std::string encoded_string(encodedBytes, '=');
-
-    // read blocks of 3 bytes
-    for (size_t ib3 = 0; ib3 < length / 3; ib3++)
-    {
-        const size_t iByte = ib3 * 3;
-        const size_t iEncodedByte = ib3 * 4;
-        const char* currData = &data[iByte];
-
-        EncodeByteBlock(currData, encoded_string, iEncodedByte);
-    }
-
-    // if size of data is not a multiple of 3, also encode the final bytes (and add zeros where needed)
-    if (extraBytes > 0)
-    {
-        char finalBytes[4] = { 0,0,0,0 };
-        memcpy(&finalBytes[0], &data[length - length % 3], length % 3);
-
-        const size_t iEncodedByte = encodedBytes - 4;
-        EncodeByteBlock(&finalBytes[0], encoded_string, iEncodedByte);
-
-        // add '=' at the end
-        for (size_t i = 0; i < 4 * extraBytes / 3; i++)
-            encoded_string[encodedBytes - i - 1] = '=';
-    }
-    return encoded_string;
-}
-
-} // !Util
-} // !FBX
-} // !Assimp
-
-#endif

+ 0 - 137
thirdparty/assimp/code/FBX/FBXUtil.h

@@ -1,137 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file  FBXUtil.h
- *  @brief FBX utility functions for internal use
- */
-#ifndef INCLUDED_AI_FBX_UTIL_H
-#define INCLUDED_AI_FBX_UTIL_H
-
-#include "FBXCompileConfig.h"
-#include "FBXTokenizer.h"
-#include <stdint.h>
-
-namespace Assimp {
-namespace FBX {
-
-
-namespace Util {
-
-
-/** helper for std::for_each to delete all heap-allocated items in a container */
-template<typename T>
-struct delete_fun
-{
-    void operator()(const volatile T* del) {
-        delete del;
-    }
-};
-
-/** Get a string representation for a #TokenType. */
-const char* TokenTypeString(TokenType t);
-
-
-
-/** Format log/error messages using a given offset in the source binary file
- *
- *  @param prefix Message prefix to be preprended to the location info.
- *  @param text Message text
- *  @param line Line index, 1-based
- *  @param column Column index, 1-based
- *  @return A string of the following format: {prefix} (offset 0x{offset}) {text}*/
-std::string AddOffset(const std::string& prefix, const std::string& text, size_t offset);
-
-
-/** Format log/error messages using a given line location in the source file.
- *
- *  @param prefix Message prefix to be preprended to the location info.
- *  @param text Message text
- *  @param line Line index, 1-based
- *  @param column Column index, 1-based
- *  @return A string of the following format: {prefix} (line {line}, col {column}) {text}*/
-std::string AddLineAndColumn(const std::string& prefix, const std::string& text, unsigned int line, unsigned int column);
-
-
-/** Format log/error messages using a given cursor token.
- *
- *  @param prefix Message prefix to be preprended to the location info.
- *  @param text Message text
- *  @param tok Token where parsing/processing stopped
- *  @return A string of the following format: {prefix} ({token-type}, line {line}, col {column}) {text}*/
-std::string AddTokenText(const std::string& prefix, const std::string& text, const Token* tok);
-
-/** Decode a single Base64-encoded character.
-*
-*  @param ch Character to decode (from base64 to binary).
-*  @return decoded byte value*/
-uint8_t DecodeBase64(char ch);
-
-/** Compute decoded size of a Base64-encoded string
-*
-*  @param in Characters to decode.
-*  @param inLength Number of characters to decode.
-*  @return size of the decoded data (number of bytes)*/
-size_t ComputeDecodedSizeBase64(const char* in, size_t inLength);
-
-/** Decode a Base64-encoded string
-*
-*  @param in Characters to decode.
-*  @param inLength Number of characters to decode.
-*  @param out Pointer where we will store the decoded data.
-*  @param maxOutLength Size of output buffer.
-*  @return size of the decoded data (number of bytes)*/
-size_t DecodeBase64(const char* in, size_t inLength, uint8_t* out, size_t maxOutLength);
-
-char EncodeBase64(char byte);
-
-/** Encode bytes in base64-encoding
-*
-*  @param data Binary data to encode.
-*  @param inLength Number of bytes to encode.
-*  @return base64-encoded string*/
-std::string EncodeBase64(const char* data, size_t length);
-
-}
-}
-}
-
-#endif // ! INCLUDED_AI_FBX_UTIL_H

+ 0 - 632
thirdparty/assimp/code/Material/MaterialSystem.cpp

@@ -1,632 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file  MaterialSystem.cpp
- *  @brief Implementation of the material system of the library
- */
-
-#include <assimp/Hash.h>
-#include <assimp/fast_atof.h>
-#include <assimp/ParsingUtils.h>
-#include "MaterialSystem.h"
-#include <assimp/types.h>
-#include <assimp/material.h>
-#include <assimp/DefaultLogger.hpp>
-
-using namespace Assimp;
-
-// ------------------------------------------------------------------------------------------------
-// Get a specific property from a material
-aiReturn aiGetMaterialProperty(const aiMaterial* pMat,
-    const char* pKey,
-    unsigned int type,
-    unsigned int index,
-    const aiMaterialProperty** pPropOut)
-{
-    ai_assert( pMat != NULL );
-    ai_assert( pKey != NULL );
-    ai_assert( pPropOut != NULL );
-
-    /*  Just search for a property with exactly this name ..
-     *  could be improved by hashing, but it's possibly
-     *  no worth the effort (we're bound to C structures,
-     *  thus std::map or derivates are not applicable. */
-    for ( unsigned int i = 0; i < pMat->mNumProperties; ++i ) {
-        aiMaterialProperty* prop = pMat->mProperties[i];
-
-        if (prop /* just for safety ... */
-            && 0 == strcmp( prop->mKey.data, pKey )
-            && (UINT_MAX == type  || prop->mSemantic == type) /* UINT_MAX is a wild-card, but this is undocumented :-) */
-            && (UINT_MAX == index || prop->mIndex == index))
-        {
-            *pPropOut = pMat->mProperties[i];
-            return AI_SUCCESS;
-        }
-    }
-    *pPropOut = NULL;
-    return AI_FAILURE;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Get an array of floating-point values from the material.
-aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat,
-    const char* pKey,
-    unsigned int type,
-    unsigned int index,
-    ai_real* pOut,
-    unsigned int* pMax)
-{
-    ai_assert( pOut != nullptr );
-    ai_assert( pMat != nullptr );
-
-    const aiMaterialProperty* prop;
-    aiGetMaterialProperty(pMat,pKey,type,index, (const aiMaterialProperty**) &prop);
-    if ( nullptr == prop) {
-        return AI_FAILURE;
-    }
-
-    // data is given in floats, convert to ai_real
-    unsigned int iWrite = 0;
-    if( aiPTI_Float == prop->mType || aiPTI_Buffer == prop->mType)  {
-        iWrite = prop->mDataLength / sizeof(float);
-        if (pMax) {
-            iWrite = std::min(*pMax,iWrite); ;
-        }
-
-        for (unsigned int a = 0; a < iWrite; ++a) {
-            pOut[ a ] = static_cast<ai_real> ( reinterpret_cast<float*>(prop->mData)[a] );
-        }
-
-        if (pMax) {
-            *pMax = iWrite;
-        }
-    }
-    // data is given in doubles, convert to float
-    else if( aiPTI_Double == prop->mType)  {
-        iWrite = prop->mDataLength / sizeof(double);
-        if (pMax) {
-            iWrite = std::min(*pMax,iWrite); ;
-        }
-        for (unsigned int a = 0; a < iWrite;++a)    {
-            pOut[a] = static_cast<ai_real> ( reinterpret_cast<double*>(prop->mData)[a] );
-        }
-        if (pMax) {
-            *pMax = iWrite;
-        }
-    }
-    // data is given in ints, convert to float
-    else if( aiPTI_Integer == prop->mType)  {
-        iWrite = prop->mDataLength / sizeof(int32_t);
-        if (pMax) {
-            iWrite = std::min(*pMax,iWrite); ;
-        }
-        for (unsigned int a = 0; a < iWrite;++a)    {
-            pOut[a] = static_cast<ai_real> ( reinterpret_cast<int32_t*>(prop->mData)[a] );
-        }
-        if (pMax) {
-            *pMax = iWrite;
-        }
-    }
-    // a string ... read floats separated by spaces
-    else {
-        if (pMax) {
-            iWrite = *pMax;
-        }
-        // strings are zero-terminated with a 32 bit length prefix, so this is safe
-        const char *cur = prop->mData + 4;
-        ai_assert( prop->mDataLength >= 5 );
-        ai_assert( !prop->mData[ prop->mDataLength - 1 ] );
-        for ( unsigned int a = 0; ;++a) {
-            cur = fast_atoreal_move<ai_real>(cur,pOut[a]);
-            if ( a==iWrite-1 ) {
-                break;
-            }
-            if ( !IsSpace(*cur) ) {
-                ASSIMP_LOG_ERROR("Material property" + std::string(pKey) +
-                    " is a string; failed to parse a float array out of it.");
-                return AI_FAILURE;
-            }
-        }
-
-        if (pMax) {
-            *pMax = iWrite;
-        }
-    }
-    return AI_SUCCESS;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Get an array if integers from the material
-aiReturn aiGetMaterialIntegerArray(const aiMaterial* pMat,
-    const char* pKey,
-    unsigned int type,
-    unsigned int index,
-    int* pOut,
-    unsigned int* pMax)
-{
-    ai_assert( pOut != NULL );
-    ai_assert( pMat != NULL );
-
-    const aiMaterialProperty* prop;
-    aiGetMaterialProperty(pMat,pKey,type,index,(const aiMaterialProperty**) &prop);
-    if (!prop) {
-        return AI_FAILURE;
-    }
-
-    // data is given in ints, simply copy it
-    unsigned int iWrite = 0;
-    if( aiPTI_Integer == prop->mType || aiPTI_Buffer == prop->mType)    {
-        iWrite = std::max(static_cast<unsigned int>(prop->mDataLength / sizeof(int32_t)), 1u);
-        if (pMax) {
-            iWrite = std::min(*pMax,iWrite);
-        }
-        if (1 == prop->mDataLength) {
-            // bool type, 1 byte
-            *pOut = static_cast<int>(*prop->mData);
-        }
-        else {
-            for (unsigned int a = 0; a < iWrite;++a) {
-                pOut[a] = static_cast<int>(reinterpret_cast<int32_t*>(prop->mData)[a]);
-            }
-        }
-        if (pMax) {
-            *pMax = iWrite;
-        }
-    }
-    // data is given in floats convert to int
-    else if( aiPTI_Float == prop->mType)    {
-        iWrite = prop->mDataLength / sizeof(float);
-        if (pMax) {
-            iWrite = std::min(*pMax,iWrite); ;
-        }
-        for (unsigned int a = 0; a < iWrite;++a) {
-            pOut[a] = static_cast<int>(reinterpret_cast<float*>(prop->mData)[a]);
-        }
-        if (pMax) {
-            *pMax = iWrite;
-        }
-    }
-    // it is a string ... no way to read something out of this
-    else    {
-        if (pMax) {
-            iWrite = *pMax;
-        }
-        // strings are zero-terminated with a 32 bit length prefix, so this is safe
-        const char *cur =  prop->mData+4;
-        ai_assert( prop->mDataLength >= 5 );
-        ai_assert( !prop->mData[ prop->mDataLength - 1 ] );
-        for (unsigned int a = 0; ;++a) {
-            pOut[a] = strtol10(cur,&cur);
-            if(a==iWrite-1) {
-                break;
-            }
-            if(!IsSpace(*cur)) {
-                ASSIMP_LOG_ERROR("Material property" + std::string(pKey) +
-                    " is a string; failed to parse an integer array out of it.");
-                return AI_FAILURE;
-            }
-        }
-
-        if (pMax) {
-            *pMax = iWrite;
-        }
-    }
-    return AI_SUCCESS;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Get a color (3 or 4 floats) from the material
-aiReturn aiGetMaterialColor(const aiMaterial* pMat,
-    const char* pKey,
-    unsigned int type,
-    unsigned int index,
-    aiColor4D* pOut)
-{
-    unsigned int iMax = 4;
-    const aiReturn eRet = aiGetMaterialFloatArray(pMat,pKey,type,index,(ai_real*)pOut,&iMax);
-
-    // if no alpha channel is defined: set it to 1.0
-    if (3 == iMax) {
-        pOut->a = 1.0;
-    }
-
-    return eRet;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Get a aiUVTransform (4 floats) from the material
-aiReturn aiGetMaterialUVTransform(const aiMaterial* pMat,
-    const char* pKey,
-    unsigned int type,
-    unsigned int index,
-    aiUVTransform* pOut)
-{
-    unsigned int iMax = 4;
-    return aiGetMaterialFloatArray(pMat,pKey,type,index,(ai_real*)pOut,&iMax);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Get a string from the material
-aiReturn aiGetMaterialString(const aiMaterial* pMat,
-    const char* pKey,
-    unsigned int type,
-    unsigned int index,
-    aiString* pOut)
-{
-    ai_assert (pOut != NULL);
-
-    const aiMaterialProperty* prop;
-    aiGetMaterialProperty(pMat,pKey,type,index,(const aiMaterialProperty**)&prop);
-    if (!prop) {
-        return AI_FAILURE;
-    }
-
-    if( aiPTI_String == prop->mType) {
-        ai_assert(prop->mDataLength>=5);
-
-        // The string is stored as 32 but length prefix followed by zero-terminated UTF8 data
-        pOut->length = static_cast<unsigned int>(*reinterpret_cast<uint32_t*>(prop->mData));
-
-        ai_assert( pOut->length+1+4==prop->mDataLength );
-        ai_assert( !prop->mData[ prop->mDataLength - 1 ] );
-        memcpy(pOut->data,prop->mData+4,pOut->length+1);
-    }
-    else {
-        // TODO - implement lexical cast as well
-        ASSIMP_LOG_ERROR("Material property" + std::string(pKey) +
-            " was found, but is no string" );
-        return AI_FAILURE;
-    }
-    return AI_SUCCESS;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Get the number of textures on a particular texture stack
-unsigned int aiGetMaterialTextureCount(const C_STRUCT aiMaterial* pMat,
-    C_ENUM aiTextureType type)
-{
-    ai_assert (pMat != NULL);
-
-    // Textures are always stored with ascending indices (ValidateDS provides a check, so we don't need to do it again)
-    unsigned int max = 0;
-    for (unsigned int i = 0; i < pMat->mNumProperties;++i) {
-        aiMaterialProperty* prop = pMat->mProperties[i];
-
-        if ( prop /* just a sanity check ... */
-            && 0 == strcmp( prop->mKey.data, _AI_MATKEY_TEXTURE_BASE )
-            && prop->mSemantic == type) {
-
-            max = std::max(max,prop->mIndex+1);
-        }
-    }
-    return max;
-}
-
-// ------------------------------------------------------------------------------------------------
-aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial* mat,
-    aiTextureType type,
-    unsigned int  index,
-    C_STRUCT aiString* path,
-    aiTextureMapping* _mapping  /*= NULL*/,
-    unsigned int* uvindex       /*= NULL*/,
-    ai_real* blend              /*= NULL*/,
-    aiTextureOp* op             /*= NULL*/,
-    aiTextureMapMode* mapmode   /*= NULL*/,
-    unsigned int* flags         /*= NULL*/
-    )
-{
-    ai_assert( NULL != mat );
-    ai_assert( NULL != path );
-
-    // Get the path to the texture
-    if (AI_SUCCESS != aiGetMaterialString(mat,AI_MATKEY_TEXTURE(type,index),path))  {
-        return AI_FAILURE;
-    }
-
-    // Determine mapping type
-    int mapping_ = static_cast<int>(aiTextureMapping_UV);
-    aiGetMaterialInteger(mat,AI_MATKEY_MAPPING(type,index), &mapping_);
-    aiTextureMapping mapping = static_cast<aiTextureMapping>(mapping_);
-    if (_mapping)
-        *_mapping = mapping;
-
-    // Get UV index
-    if (aiTextureMapping_UV == mapping && uvindex)  {
-        aiGetMaterialInteger(mat,AI_MATKEY_UVWSRC(type,index),(int*)uvindex);
-    }
-    // Get blend factor
-    if (blend)  {
-        aiGetMaterialFloat(mat,AI_MATKEY_TEXBLEND(type,index),blend);
-    }
-    // Get texture operation
-    if (op){
-        aiGetMaterialInteger(mat,AI_MATKEY_TEXOP(type,index),(int*)op);
-    }
-    // Get texture mapping modes
-    if (mapmode)    {
-        aiGetMaterialInteger(mat,AI_MATKEY_MAPPINGMODE_U(type,index),(int*)&mapmode[0]);
-        aiGetMaterialInteger(mat,AI_MATKEY_MAPPINGMODE_V(type,index),(int*)&mapmode[1]);
-    }
-    // Get texture flags
-    if (flags){
-        aiGetMaterialInteger(mat,AI_MATKEY_TEXFLAGS(type,index),(int*)flags);
-    }
-
-    return AI_SUCCESS;
-}
-
-
-static const unsigned int DefaultNumAllocated = 5;
-
-// ------------------------------------------------------------------------------------------------
-// Construction. Actually the one and only way to get an aiMaterial instance
-aiMaterial::aiMaterial() 
-: mProperties( nullptr )
-, mNumProperties( 0 )
-, mNumAllocated( DefaultNumAllocated ) {
-    // Allocate 5 entries by default
-    mProperties = new aiMaterialProperty*[ DefaultNumAllocated ];
-}
-
-// ------------------------------------------------------------------------------------------------
-aiMaterial::~aiMaterial()
-{
-    Clear();
-
-    delete[] mProperties;
-}
-
-// ------------------------------------------------------------------------------------------------
-aiString aiMaterial::GetName() {
-    aiString name;
-    Get(AI_MATKEY_NAME, name);
-
-    return name;
-}
-
-// ------------------------------------------------------------------------------------------------
-void aiMaterial::Clear()
-{
-    for ( unsigned int i = 0; i < mNumProperties; ++i )    {
-        // delete this entry
-        delete mProperties[ i ];
-        AI_DEBUG_INVALIDATE_PTR(mProperties[i]);
-    }
-    mNumProperties = 0;
-
-    // The array remains allocated, we just invalidated its contents
-}
-
-// ------------------------------------------------------------------------------------------------
-aiReturn aiMaterial::RemoveProperty ( const char* pKey,unsigned int type, unsigned int index )
-{
-    ai_assert( nullptr != pKey );
-
-    for (unsigned int i = 0; i < mNumProperties;++i) {
-        aiMaterialProperty* prop = mProperties[i];
-
-        if (prop && !strcmp( prop->mKey.data, pKey ) &&
-            prop->mSemantic == type && prop->mIndex == index)
-        {
-            // Delete this entry
-            delete mProperties[i];
-
-            // collapse the array behind --.
-            --mNumProperties;
-            for (unsigned int a = i; a < mNumProperties;++a)    {
-                mProperties[a] = mProperties[a+1];
-            }
-            return AI_SUCCESS;
-        }
-    }
-
-    return AI_FAILURE;
-}
-
-// ------------------------------------------------------------------------------------------------
-aiReturn aiMaterial::AddBinaryProperty (const void* pInput,
-    unsigned int pSizeInBytes,
-    const char* pKey,
-    unsigned int type,
-    unsigned int index,
-    aiPropertyTypeInfo pType
-    )
-{
-    ai_assert( pInput != NULL );
-    ai_assert( pKey != NULL );
-    ai_assert( 0 != pSizeInBytes );
-
-    if ( 0 == pSizeInBytes ) {
-
-    }
-
-    // first search the list whether there is already an entry with this key
-    unsigned int iOutIndex( UINT_MAX );
-    for ( unsigned int i = 0; i < mNumProperties; ++i ) {
-        aiMaterialProperty *prop( mProperties[ i ] );
-
-        if (prop /* just for safety */ && !strcmp( prop->mKey.data, pKey ) &&
-            prop->mSemantic == type && prop->mIndex == index){
-
-            delete mProperties[i];
-            iOutIndex = i;
-        }
-    }
-
-    // Allocate a new material property
-    aiMaterialProperty* pcNew = new aiMaterialProperty();
-
-    // .. and fill it
-    pcNew->mType = pType;
-    pcNew->mSemantic = type;
-    pcNew->mIndex = index;
-
-    pcNew->mDataLength = pSizeInBytes;
-    pcNew->mData = new char[pSizeInBytes];
-    memcpy (pcNew->mData,pInput,pSizeInBytes);
-
-    pcNew->mKey.length = ::strlen(pKey);
-    ai_assert ( MAXLEN > pcNew->mKey.length);
-    strcpy( pcNew->mKey.data, pKey );
-
-    if (UINT_MAX != iOutIndex)  {
-        mProperties[iOutIndex] = pcNew;
-        return AI_SUCCESS;
-    }
-
-    // resize the array ... double the storage allocated
-    if (mNumProperties == mNumAllocated)    {
-        const unsigned int iOld = mNumAllocated;
-        mNumAllocated *= 2;
-
-        aiMaterialProperty** ppTemp;
-        try {
-            ppTemp = new aiMaterialProperty*[mNumAllocated];
-        } catch (std::bad_alloc&) {
-            delete pcNew;
-            return AI_OUTOFMEMORY;
-        }
-
-        // just copy all items over; then replace the old array
-        memcpy (ppTemp,mProperties,iOld * sizeof(void*));
-
-        delete[] mProperties;
-        mProperties = ppTemp;
-    }
-    // push back ...
-    mProperties[mNumProperties++] = pcNew;
-
-    return AI_SUCCESS;
-}
-
-// ------------------------------------------------------------------------------------------------
-aiReturn aiMaterial::AddProperty (const aiString* pInput,
-    const char* pKey,
-    unsigned int type,
-    unsigned int index)
-{
-    ai_assert(sizeof(ai_uint32)==4);
-    return AddBinaryProperty(pInput,
-        static_cast<unsigned int>(pInput->length+1+4),
-        pKey,
-        type,
-        index,
-        aiPTI_String);
-}
-
-// ------------------------------------------------------------------------------------------------
-uint32_t Assimp::ComputeMaterialHash(const aiMaterial* mat, bool includeMatName /*= false*/)
-{
-    uint32_t hash = 1503; // magic start value, chosen to be my birthday :-)
-    for ( unsigned int i = 0; i < mat->mNumProperties; ++i ) {
-        aiMaterialProperty* prop;
-
-        // Exclude all properties whose first character is '?' from the hash
-        // See doc for aiMaterialProperty.
-        if ((prop = mat->mProperties[i]) && (includeMatName || prop->mKey.data[0] != '?'))  {
-
-            hash = SuperFastHash(prop->mKey.data,(unsigned int)prop->mKey.length,hash);
-            hash = SuperFastHash(prop->mData,prop->mDataLength,hash);
-
-            // Combine the semantic and the index with the hash
-            hash = SuperFastHash((const char*)&prop->mSemantic,sizeof(unsigned int),hash);
-            hash = SuperFastHash((const char*)&prop->mIndex,sizeof(unsigned int),hash);
-        }
-    }
-    return hash;
-}
-
-// ------------------------------------------------------------------------------------------------
-void aiMaterial::CopyPropertyList(aiMaterial* pcDest,
-    const aiMaterial* pcSrc
-    )
-{
-    ai_assert(NULL != pcDest);
-    ai_assert(NULL != pcSrc);
-
-    unsigned int iOldNum = pcDest->mNumProperties;
-    pcDest->mNumAllocated += pcSrc->mNumAllocated;
-    pcDest->mNumProperties += pcSrc->mNumProperties;
-
-    aiMaterialProperty** pcOld = pcDest->mProperties;
-    pcDest->mProperties = new aiMaterialProperty*[pcDest->mNumAllocated];
-
-    if (iOldNum && pcOld)   {
-        for (unsigned int i = 0; i < iOldNum;++i) {
-            pcDest->mProperties[i] = pcOld[i];
-        }
-    }
-
-    if ( pcOld ) {
-        delete[] pcOld;
-    }
-
-    for (unsigned int i = iOldNum; i< pcDest->mNumProperties;++i)   {
-        aiMaterialProperty* propSrc = pcSrc->mProperties[i];
-
-        // search whether we have already a property with this name -> if yes, overwrite it
-        aiMaterialProperty* prop;
-        for ( unsigned int q = 0; q < iOldNum; ++q ) {
-            prop = pcDest->mProperties[q];
-            if (prop /* just for safety */ && prop->mKey == propSrc->mKey && prop->mSemantic == propSrc->mSemantic
-                && prop->mIndex == propSrc->mIndex) {
-                delete prop;
-
-                // collapse the whole array ...
-                memmove(&pcDest->mProperties[q],&pcDest->mProperties[q+1],i-q);
-                i--;
-                pcDest->mNumProperties--;
-            }
-        }
-
-        // Allocate the output property and copy the source property
-        prop = pcDest->mProperties[i] = new aiMaterialProperty();
-        prop->mKey = propSrc->mKey;
-        prop->mDataLength = propSrc->mDataLength;
-        prop->mType = propSrc->mType;
-        prop->mSemantic = propSrc->mSemantic;
-        prop->mIndex = propSrc->mIndex;
-
-        prop->mData = new char[propSrc->mDataLength];
-        memcpy(prop->mData,propSrc->mData,prop->mDataLength);
-    }
-}

+ 0 - 72
thirdparty/assimp/code/Material/MaterialSystem.h

@@ -1,72 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file MaterialSystem.h
- *  Now that #MaterialHelper is gone, this file only contains some
- *  internal material utility functions.
- */
-#ifndef AI_MATERIALSYSTEM_H_INC
-#define AI_MATERIALSYSTEM_H_INC
-
-#include <stdint.h>
-
-struct aiMaterial;
-
-namespace Assimp    {
-
-// ------------------------------------------------------------------------------
-/** Computes a hash (hopefully unique) from all material properties
- *  The hash value reflects the current property state, so if you add any
- *  property and call this method again, the resulting hash value will be
- *  different. The hash is not persistent across different builds and platforms.
- *
- *  @param  includeMatName Set to 'true' to take all properties with
- *    '?' as initial character in their name into account.
- *    Currently #AI_MATKEY_NAME is the only example.
- *  @return 32 Bit jash value for the material
- */
-uint32_t ComputeMaterialHash(const aiMaterial* mat, bool includeMatName = false);
-
-
-} // ! namespace Assimp
-
-#endif //!! AI_MATERIALSYSTEM_H_INC

+ 0 - 268
thirdparty/assimp/code/PostProcessing/ArmaturePopulate.cpp

@@ -1,268 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, 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 "ArmaturePopulate.h"
-
-#include <assimp/BaseImporter.h>
-#include <assimp/DefaultLogger.hpp>
-#include <assimp/postprocess.h>
-#include <assimp/scene.h>
-#include <iostream>
-
-namespace Assimp {
-
-/// The default class constructor.
-ArmaturePopulate::ArmaturePopulate() : BaseProcess()
-{}
-
-/// The class destructor.
-ArmaturePopulate::~ArmaturePopulate() 
-{}
-
-bool ArmaturePopulate::IsActive(unsigned int pFlags) const {
-  return (pFlags & aiProcess_PopulateArmatureData) != 0;
-}
-
-void ArmaturePopulate::SetupProperties(const Importer *pImp) {
-  // do nothing
-}
-
-void ArmaturePopulate::Execute(aiScene *out) {
-
-  // Now convert all bone positions to the correct mOffsetMatrix
-  std::vector<aiBone *> bones;
-  std::vector<aiNode *> nodes;
-  std::map<aiBone *, aiNode *> bone_stack;
-  BuildBoneList(out->mRootNode, out->mRootNode, out, bones);
-  BuildNodeList(out->mRootNode, nodes);
-
-  BuildBoneStack(out->mRootNode, out->mRootNode, out, bones, bone_stack, nodes);
-
-  ASSIMP_LOG_DEBUG_F("Bone stack size: ", bone_stack.size());
-
-  for (std::pair<aiBone *, aiNode *> kvp : bone_stack) {
-    aiBone *bone = kvp.first;
-    aiNode *bone_node = kvp.second;
-    ASSIMP_LOG_DEBUG_F("active node lookup: ", bone->mName.C_Str());
-    // lcl transform grab - done in generate_nodes :)
-
-    // bone->mOffsetMatrix = bone_node->mTransformation;
-    aiNode *armature = GetArmatureRoot(bone_node, bones);
-
-    ai_assert(armature);
-
-    // set up bone armature id
-    bone->mArmature = armature;
-
-    // set this bone node to be referenced properly
-    ai_assert(bone_node);
-    bone->mNode = bone_node;
-  }
-}
-
-
-/* Reprocess all nodes to calculate bone transforms properly based on the REAL
- * mOffsetMatrix not the local. */
-/* Before this would use mesh transforms which is wrong for bone transforms */
-/* Before this would work for simple character skeletons but not complex meshes
- * with multiple origins */
-/* Source: sketch fab log cutter fbx */
-void ArmaturePopulate::BuildBoneList(aiNode *current_node,
-                                     const aiNode *root_node,
-                                     const aiScene *scene,
-                                     std::vector<aiBone *> &bones) {
-  ai_assert(scene);
-  for (unsigned int nodeId = 0; nodeId < current_node->mNumChildren; ++nodeId) {
-    aiNode *child = current_node->mChildren[nodeId];
-    ai_assert(child);
-
-    // check for bones
-    for (unsigned int meshId = 0; meshId < child->mNumMeshes; ++meshId) {
-      ai_assert(child->mMeshes);
-      unsigned int mesh_index = child->mMeshes[meshId];
-      aiMesh *mesh = scene->mMeshes[mesh_index];
-      ai_assert(mesh);
-
-      for (unsigned int boneId = 0; boneId < mesh->mNumBones; ++boneId) {
-        aiBone *bone = mesh->mBones[boneId];
-        ai_assert(bone);
-
-        // duplicate meshes exist with the same bones sometimes :)
-        // so this must be detected
-        if (std::find(bones.begin(), bones.end(), bone) == bones.end()) {
-          // add the element once
-          bones.push_back(bone);
-        }
-      }
-
-      // find mesh and get bones
-      // then do recursive lookup for bones in root node hierarchy
-    }
-
-    BuildBoneList(child, root_node, scene, bones);
-  }
-}
-
-/* Prepare flat node list which can be used for non recursive lookups later */
-void ArmaturePopulate::BuildNodeList(const aiNode *current_node,
-                                     std::vector<aiNode *> &nodes) {
-  ai_assert(current_node);
-
-  for (unsigned int nodeId = 0; nodeId < current_node->mNumChildren; ++nodeId) {
-    aiNode *child = current_node->mChildren[nodeId];
-    ai_assert(child);
-
-    nodes.push_back(child);
-
-    BuildNodeList(child, nodes);
-  }
-}
-
-/* A bone stack allows us to have multiple armatures, with the same bone names
- * A bone stack allows us also to retrieve bones true transform even with
- * duplicate names :)
- */
-void ArmaturePopulate::BuildBoneStack(aiNode *current_node,
-                                      const aiNode *root_node,
-                                      const aiScene *scene,
-                                      const std::vector<aiBone *> &bones,
-                                      std::map<aiBone *, aiNode *> &bone_stack,
-                                      std::vector<aiNode *> &node_stack) {
-  ai_assert(scene);
-  ai_assert(root_node);
-  ai_assert(!node_stack.empty());
-
-  for (aiBone *bone : bones) {
-    ai_assert(bone);
-    aiNode *node = GetNodeFromStack(bone->mName, node_stack);
-    if (node == nullptr) {
-      node_stack.clear();
-      BuildNodeList(root_node, node_stack);
-      ASSIMP_LOG_DEBUG_F("Resetting bone stack: nullptr element ", bone->mName.C_Str());
-
-      node = GetNodeFromStack(bone->mName, node_stack);
-
-      if (!node) {
-        ASSIMP_LOG_ERROR("serious import issue node for bone was not detected");
-        continue;
-      }
-    }
-
-    ASSIMP_LOG_DEBUG_F("Successfully added bone[", bone->mName.C_Str(), "] to stack and bone node is: ", node->mName.C_Str());
-
-    bone_stack.insert(std::pair<aiBone *, aiNode *>(bone, node));
-  }
-}
-
-
-/* Returns the armature root node */
-/* This is required to be detected for a bone initially, it will recurse up
- * until it cannot find another bone and return the node No known failure
- * points. (yet)
- */
-aiNode *ArmaturePopulate::GetArmatureRoot(aiNode *bone_node,
-                                          std::vector<aiBone *> &bone_list) {
-  while (bone_node) {
-    if (!IsBoneNode(bone_node->mName, bone_list)) {
-      ASSIMP_LOG_DEBUG_F("GetArmatureRoot() Found valid armature: ", bone_node->mName.C_Str());
-      return bone_node;
-    }
-
-    bone_node = bone_node->mParent;
-  }
-  
-  ASSIMP_LOG_ERROR("GetArmatureRoot() can't find armature!");
-  
-  return nullptr;
-}
-
-
-
-/* Simple IsBoneNode check if this could be a bone */
-bool ArmaturePopulate::IsBoneNode(const aiString &bone_name,
-                                  std::vector<aiBone *> &bones) {
-  for (aiBone *bone : bones) {
-    if (bone->mName == bone_name) {
-      return true;
-    }
-  }
-
-  return false;
-}
-
-/* Pop this node by name from the stack if found */
-/* Used in multiple armature situations with duplicate node / bone names */
-/* Known flaw: cannot have nodes with bone names, will be fixed in later release
- */
-/* (serious to be fixed) Known flaw: nodes which have more than one bone could
- * be prematurely dropped from stack */
-aiNode *ArmaturePopulate::GetNodeFromStack(const aiString &node_name,
-                                           std::vector<aiNode *> &nodes) {
-  std::vector<aiNode *>::iterator iter;
-  aiNode *found = nullptr;
-  for (iter = nodes.begin(); iter < nodes.end(); ++iter) {
-    aiNode *element = *iter;
-    ai_assert(element);
-    // node valid and node name matches
-    if (element->mName == node_name) {
-      found = element;
-      break;
-    }
-  }
-
-  if (found != nullptr) {
-    ASSIMP_LOG_INFO_F("Removed node from stack: ", found->mName.C_Str());
-    // now pop the element from the node list
-    nodes.erase(iter);
-
-    return found;
-  }
-
-  // unique names can cause this problem
-  ASSIMP_LOG_ERROR("[Serious] GetNodeFromStack() can't find node from stack!");
-
-  return nullptr;
-}
-
-
-
-
-} // Namespace Assimp

+ 0 - 112
thirdparty/assimp/code/PostProcessing/ArmaturePopulate.h

@@ -1,112 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, 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 ARMATURE_POPULATE_H_
-#define ARMATURE_POPULATE_H_
-
-#include "Common/BaseProcess.h"
-#include <assimp/BaseImporter.h>
-#include <vector>
-#include <map>
-
-
-struct aiNode;
-struct aiBone;
-
-namespace Assimp {
-
-// ---------------------------------------------------------------------------
-/** Armature Populate: This is a post process designed
- * To save you time when importing models into your game engines
- * This was originally designed only for fbx but will work with other formats
- * it is intended to auto populate aiBone data with armature and the aiNode
- * This is very useful when dealing with skinned meshes
- * or when dealing with many different skeletons
- * It's off by default but recommend that you try it and use it
- * It should reduce down any glue code you have in your
- * importers
- * You can contact RevoluPowered <[email protected]>
- * For more info about this
-*/
-class ASSIMP_API ArmaturePopulate : public BaseProcess {
-public:
-    /// The default class constructor.
-    ArmaturePopulate();
-
-    /// The class destructor.
-    virtual ~ArmaturePopulate();
-
-    /// Overwritten, @see BaseProcess
-    virtual bool IsActive( unsigned int pFlags ) const;
-
-    /// Overwritten, @see BaseProcess
-    virtual void SetupProperties( const Importer* pImp );
-
-    /// Overwritten, @see BaseProcess
-    virtual void Execute( aiScene* pScene );
-
-    static aiNode *GetArmatureRoot(aiNode *bone_node,
-                                      std::vector<aiBone *> &bone_list);
-
-    static bool IsBoneNode(const aiString &bone_name,
-                              std::vector<aiBone *> &bones);
-
-    static aiNode *GetNodeFromStack(const aiString &node_name,
-                                       std::vector<aiNode *> &nodes);
-
-    static void BuildNodeList(const aiNode *current_node,
-                                 std::vector<aiNode *> &nodes);
-
-    static void BuildBoneList(aiNode *current_node, const aiNode *root_node,
-                                 const aiScene *scene,
-                                 std::vector<aiBone *> &bones);                        
-
-    static void BuildBoneStack(aiNode *current_node, const aiNode *root_node,
-                                  const aiScene *scene,
-                                  const std::vector<aiBone *> &bones,
-                                  std::map<aiBone *, aiNode *> &bone_stack,
-                                  std::vector<aiNode *> &node_stack);
-};
-
-} // Namespace Assimp
-
-
-#endif // SCALE_PROCESS_H_

+ 0 - 319
thirdparty/assimp/code/PostProcessing/CalcTangentsProcess.cpp

@@ -1,319 +0,0 @@
-/*
----------------------------------------------------------------------------
-Open Asset Import Library (assimp)
----------------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the following
-conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------------
-*/
-
-/** @file Implementation of the post processing step to calculate
- *  tangents and bitangents for all imported meshes
- */
-
-// internal headers
-#include "CalcTangentsProcess.h"
-#include "ProcessHelper.h"
-#include <assimp/TinyFormatter.h>
-#include <assimp/qnan.h>
-
-using namespace Assimp;
-
-// ------------------------------------------------------------------------------------------------
-// Constructor to be privately used by Importer
-CalcTangentsProcess::CalcTangentsProcess()
-: configMaxAngle( AI_DEG_TO_RAD(45.f) )
-, configSourceUV( 0 ) {
-    // nothing to do here
-}
-
-// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
-CalcTangentsProcess::~CalcTangentsProcess()
-{
-    // nothing to do here
-}
-
-// ------------------------------------------------------------------------------------------------
-// Returns whether the processing step is present in the given flag field.
-bool CalcTangentsProcess::IsActive( unsigned int pFlags) const
-{
-    return (pFlags & aiProcess_CalcTangentSpace) != 0;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Executes the post processing step on the given imported data.
-void CalcTangentsProcess::SetupProperties(const Importer* pImp)
-{
-    ai_assert( NULL != pImp );
-
-    // get the current value of the property
-    configMaxAngle = pImp->GetPropertyFloat(AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE,45.f);
-    configMaxAngle = std::max(std::min(configMaxAngle,45.0f),0.0f);
-    configMaxAngle = AI_DEG_TO_RAD(configMaxAngle);
-
-    configSourceUV = pImp->GetPropertyInteger(AI_CONFIG_PP_CT_TEXTURE_CHANNEL_INDEX,0);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Executes the post processing step on the given imported data.
-void CalcTangentsProcess::Execute( aiScene* pScene)
-{
-    ai_assert( NULL != pScene );
-
-    ASSIMP_LOG_DEBUG("CalcTangentsProcess begin");
-
-    bool bHas = false;
-    for ( unsigned int a = 0; a < pScene->mNumMeshes; a++ ) {
-        if(ProcessMesh( pScene->mMeshes[a],a))bHas = true;
-    }
-
-    if ( bHas ) {
-        ASSIMP_LOG_INFO("CalcTangentsProcess finished. Tangents have been calculated");
-    } else {
-        ASSIMP_LOG_DEBUG("CalcTangentsProcess finished");
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-// Calculates tangents and bi-tangents for the given mesh
-bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
-{
-    // we assume that the mesh is still in the verbose vertex format where each face has its own set
-    // of vertices and no vertices are shared between faces. Sadly I don't know any quick test to
-    // assert() it here.
-    // assert( must be verbose, dammit);
-
-    if (pMesh->mTangents) // this implies that mBitangents is also there
-        return false;
-
-    // If the mesh consists of lines and/or points but not of
-    // triangles or higher-order polygons the normal vectors
-    // are undefined.
-    if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON)))
-    {
-        ASSIMP_LOG_INFO("Tangents are undefined for line and point meshes");
-        return false;
-    }
-
-    // what we can check, though, is if the mesh has normals and texture coordinates. That's a requirement
-    if( pMesh->mNormals == NULL)
-    {
-        ASSIMP_LOG_ERROR("Failed to compute tangents; need normals");
-        return false;
-    }
-    if( configSourceUV >= AI_MAX_NUMBER_OF_TEXTURECOORDS || !pMesh->mTextureCoords[configSourceUV] )
-    {
-        ASSIMP_LOG_ERROR((Formatter::format("Failed to compute tangents; need UV data in channel"),configSourceUV));
-        return false;
-    }
-
-    const float angleEpsilon = 0.9999f;
-
-    std::vector<bool> vertexDone( pMesh->mNumVertices, false);
-    const float qnan = get_qnan();
-
-    // create space for the tangents and bitangents
-    pMesh->mTangents = new aiVector3D[pMesh->mNumVertices];
-    pMesh->mBitangents = new aiVector3D[pMesh->mNumVertices];
-
-    const aiVector3D* meshPos = pMesh->mVertices;
-    const aiVector3D* meshNorm = pMesh->mNormals;
-    const aiVector3D* meshTex = pMesh->mTextureCoords[configSourceUV];
-    aiVector3D* meshTang = pMesh->mTangents;
-    aiVector3D* meshBitang = pMesh->mBitangents;
-
-    // calculate the tangent and bitangent for every face
-    for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
-    {
-        const aiFace& face = pMesh->mFaces[a];
-        if (face.mNumIndices < 3)
-        {
-            // There are less than three indices, thus the tangent vector
-            // is not defined. We are finished with these vertices now,
-            // their tangent vectors are set to qnan.
-            for (unsigned int i = 0; i < face.mNumIndices;++i)
-            {
-                unsigned int idx = face.mIndices[i];
-                vertexDone  [idx] = true;
-                meshTang    [idx] = aiVector3D(qnan);
-                meshBitang  [idx] = aiVector3D(qnan);
-            }
-
-            continue;
-        }
-
-        // triangle or polygon... we always use only the first three indices. A polygon
-        // is supposed to be planar anyways....
-        // FIXME: (thom) create correct calculation for multi-vertex polygons maybe?
-        const unsigned int p0 = face.mIndices[0], p1 = face.mIndices[1], p2 = face.mIndices[2];
-
-        // position differences p1->p2 and p1->p3
-        aiVector3D v = meshPos[p1] - meshPos[p0], w = meshPos[p2] - meshPos[p0];
-
-        // texture offset p1->p2 and p1->p3
-        float sx = meshTex[p1].x - meshTex[p0].x, sy = meshTex[p1].y - meshTex[p0].y;
-        float tx = meshTex[p2].x - meshTex[p0].x, ty = meshTex[p2].y - meshTex[p0].y;
-        float dirCorrection = (tx * sy - ty * sx) < 0.0f ? -1.0f : 1.0f;
-        // when t1, t2, t3 in same position in UV space, just use default UV direction.
-        if (  sx * ty == sy * tx ) {
-            sx = 0.0; sy = 1.0;
-            tx = 1.0; ty = 0.0;
-        }
-
-        // tangent points in the direction where to positive X axis of the texture coord's would point in model space
-        // bitangent's points along the positive Y axis of the texture coord's, respectively
-        aiVector3D tangent, bitangent;
-        tangent.x = (w.x * sy - v.x * ty) * dirCorrection;
-        tangent.y = (w.y * sy - v.y * ty) * dirCorrection;
-        tangent.z = (w.z * sy - v.z * ty) * dirCorrection;
-        bitangent.x = (w.x * sx - v.x * tx) * dirCorrection;
-        bitangent.y = (w.y * sx - v.y * tx) * dirCorrection;
-        bitangent.z = (w.z * sx - v.z * tx) * dirCorrection;
-
-        // store for every vertex of that face
-        for( unsigned int b = 0; b < face.mNumIndices; ++b ) {
-            unsigned int p = face.mIndices[b];
-
-            // project tangent and bitangent into the plane formed by the vertex' normal
-            aiVector3D localTangent = tangent - meshNorm[p] * (tangent * meshNorm[p]);
-            aiVector3D localBitangent = bitangent - meshNorm[p] * (bitangent * meshNorm[p]);
-            localTangent.NormalizeSafe(); localBitangent.NormalizeSafe();
-
-            // reconstruct tangent/bitangent according to normal and bitangent/tangent when it's infinite or NaN.
-            bool invalid_tangent = is_special_float(localTangent.x) || is_special_float(localTangent.y) || is_special_float(localTangent.z);
-            bool invalid_bitangent = is_special_float(localBitangent.x) || is_special_float(localBitangent.y) || is_special_float(localBitangent.z);
-            if (invalid_tangent != invalid_bitangent) {
-                if (invalid_tangent) {
-                    localTangent = meshNorm[p] ^ localBitangent;
-                    localTangent.NormalizeSafe();
-                } else {
-                    localBitangent = localTangent ^ meshNorm[p];
-                    localBitangent.NormalizeSafe();
-                }
-            }
-
-            // and write it into the mesh.
-            meshTang[ p ]   = localTangent;
-            meshBitang[ p ] = localBitangent;
-        }
-    }
-
-
-    // create a helper to quickly find locally close vertices among the vertex array
-    // FIX: check whether we can reuse the SpatialSort of a previous step
-    SpatialSort* vertexFinder = NULL;
-    SpatialSort  _vertexFinder;
-    float posEpsilon;
-    if (shared)
-    {
-        std::vector<std::pair<SpatialSort,float> >* avf;
-        shared->GetProperty(AI_SPP_SPATIAL_SORT,avf);
-        if (avf)
-        {
-            std::pair<SpatialSort,float>& blubb = avf->operator [] (meshIndex);
-            vertexFinder = &blubb.first;
-            posEpsilon = blubb.second;;
-        }
-    }
-    if (!vertexFinder)
-    {
-        _vertexFinder.Fill(pMesh->mVertices, pMesh->mNumVertices, sizeof( aiVector3D));
-        vertexFinder = &_vertexFinder;
-        posEpsilon = ComputePositionEpsilon(pMesh);
-    }
-    std::vector<unsigned int> verticesFound;
-
-    const float fLimit = std::cos(configMaxAngle);
-    std::vector<unsigned int> closeVertices;
-
-    // in the second pass we now smooth out all tangents and bitangents at the same local position
-    // if they are not too far off.
-    for( unsigned int a = 0; a < pMesh->mNumVertices; a++)
-    {
-        if( vertexDone[a])
-            continue;
-
-        const aiVector3D& origPos = pMesh->mVertices[a];
-        const aiVector3D& origNorm = pMesh->mNormals[a];
-        const aiVector3D& origTang = pMesh->mTangents[a];
-        const aiVector3D& origBitang = pMesh->mBitangents[a];
-        closeVertices.resize( 0 );
-
-        // find all vertices close to that position
-        vertexFinder->FindPositions( origPos, posEpsilon, verticesFound);
-
-        closeVertices.reserve (verticesFound.size()+5);
-        closeVertices.push_back( a);
-
-        // look among them for other vertices sharing the same normal and a close-enough tangent/bitangent
-        for( unsigned int b = 0; b < verticesFound.size(); b++)
-        {
-            unsigned int idx = verticesFound[b];
-            if( vertexDone[idx])
-                continue;
-            if( meshNorm[idx] * origNorm < angleEpsilon)
-                continue;
-            if(  meshTang[idx] * origTang < fLimit)
-                continue;
-            if( meshBitang[idx] * origBitang < fLimit)
-                continue;
-
-            // it's similar enough -> add it to the smoothing group
-            closeVertices.push_back( idx);
-            vertexDone[idx] = true;
-        }
-
-        // smooth the tangents and bitangents of all vertices that were found to be close enough
-        aiVector3D smoothTangent( 0, 0, 0), smoothBitangent( 0, 0, 0);
-        for( unsigned int b = 0; b < closeVertices.size(); ++b)
-        {
-            smoothTangent += meshTang[ closeVertices[b] ];
-            smoothBitangent += meshBitang[ closeVertices[b] ];
-        }
-        smoothTangent.Normalize();
-        smoothBitangent.Normalize();
-
-        // and write it back into all affected tangents
-        for( unsigned int b = 0; b < closeVertices.size(); ++b)
-        {
-            meshTang[ closeVertices[b] ] = smoothTangent;
-            meshBitang[ closeVertices[b] ] = smoothBitangent;
-        }
-    }
-    return true;
-}

+ 0 - 117
thirdparty/assimp/code/PostProcessing/CalcTangentsProcess.h

@@ -1,117 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-
-/** @file Defines a post processing step to calculate tangents and
-    bi-tangents on all imported meshes.*/
-#ifndef AI_CALCTANGENTSPROCESS_H_INC
-#define AI_CALCTANGENTSPROCESS_H_INC
-
-#include "Common/BaseProcess.h"
-
-struct aiMesh;
-
-namespace Assimp
-{
-
-// ---------------------------------------------------------------------------
-/** The CalcTangentsProcess calculates the tangent and bitangent for any vertex
- * of all meshes. It is expected to be run before the JoinVerticesProcess runs
- * because the joining of vertices also considers tangents and bitangents for
- * uniqueness.
- */
-class ASSIMP_API_WINONLY CalcTangentsProcess : public BaseProcess
-{
-public:
-
-    CalcTangentsProcess();
-    ~CalcTangentsProcess();
-
-public:
-    // -------------------------------------------------------------------
-    /** Returns whether the processing step is present in the given flag.
-    * @param pFlags The processing flags the importer was called with.
-    *   A bitwise combination of #aiPostProcessSteps.
-    * @return true if the process is present in this flag fields,
-    *   false if not.
-    */
-    bool IsActive( unsigned int pFlags) const;
-
-    // -------------------------------------------------------------------
-    /** Called prior to ExecuteOnScene().
-    * The function is a request to the process to update its configuration
-    * basing on the Importer's configuration property list.
-    */
-    void SetupProperties(const Importer* pImp);
-
-
-    // setter for configMaxAngle
-    inline void SetMaxSmoothAngle(float f)
-    {
-        configMaxAngle =f;
-    }
-
-protected:
-
-    // -------------------------------------------------------------------
-    /** Calculates tangents and bitangents for a specific mesh.
-    * @param pMesh The mesh to process.
-    * @param meshIndex Index of the mesh
-    */
-    bool ProcessMesh( aiMesh* pMesh, unsigned int meshIndex);
-
-    // -------------------------------------------------------------------
-    /** Executes the post processing step on the given imported data.
-    * @param pScene The imported data to work at.
-    */
-    void Execute( aiScene* pScene);
-
-private:
-
-    /** Configuration option: maximum smoothing angle, in radians*/
-    float configMaxAngle;
-    unsigned int configSourceUV;
-};
-
-} // end of namespace Assimp
-
-#endif // AI_CALCTANGENTSPROCESS_H_INC

+ 0 - 506
thirdparty/assimp/code/PostProcessing/ComputeUVMappingProcess.cpp

@@ -1,506 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file GenUVCoords step */
-
-
-#include "ComputeUVMappingProcess.h"
-#include "ProcessHelper.h"
-#include <assimp/Exceptional.h>
-
-using namespace Assimp;
-
-namespace {
-
-    const static aiVector3D base_axis_y(0.0,1.0,0.0);
-    const static aiVector3D base_axis_x(1.0,0.0,0.0);
-    const static aiVector3D base_axis_z(0.0,0.0,1.0);
-    const static ai_real angle_epsilon = ai_real( 0.95 );
-}
-
-// ------------------------------------------------------------------------------------------------
-// Constructor to be privately used by Importer
-ComputeUVMappingProcess::ComputeUVMappingProcess()
-{
-    // nothing to do here
-}
-
-// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
-ComputeUVMappingProcess::~ComputeUVMappingProcess()
-{
-    // nothing to do here
-}
-
-// ------------------------------------------------------------------------------------------------
-// Returns whether the processing step is present in the given flag field.
-bool ComputeUVMappingProcess::IsActive( unsigned int pFlags) const
-{
-    return  (pFlags & aiProcess_GenUVCoords) != 0;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Check whether a ray intersects a plane and find the intersection point
-inline bool PlaneIntersect(const aiRay& ray, const aiVector3D& planePos,
-    const aiVector3D& planeNormal, aiVector3D& pos)
-{
-    const ai_real b = planeNormal * (planePos - ray.pos);
-    ai_real h = ray.dir * planeNormal;
-    if ((h < 10e-5 && h > -10e-5) || (h = b/h) < 0)
-        return false;
-
-    pos = ray.pos + (ray.dir * h);
-    return true;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Find the first empty UV channel in a mesh
-inline unsigned int FindEmptyUVChannel (aiMesh* mesh)
-{
-    for (unsigned int m = 0; m < AI_MAX_NUMBER_OF_TEXTURECOORDS;++m)
-        if (!mesh->mTextureCoords[m])return m;
-
-    ASSIMP_LOG_ERROR("Unable to compute UV coordinates, no free UV slot found");
-    return UINT_MAX;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Try to remove UV seams
-void RemoveUVSeams (aiMesh* mesh, aiVector3D* out)
-{
-    // TODO: just a very rough algorithm. I think it could be done
-    // much easier, but I don't know how and am currently too tired to
-    // to think about a better solution.
-
-    const static ai_real LOWER_LIMIT = ai_real( 0.1 );
-    const static ai_real UPPER_LIMIT = ai_real( 0.9 );
-
-    const static ai_real LOWER_EPSILON = ai_real( 10e-3 );
-    const static ai_real UPPER_EPSILON = ai_real( 1.0-10e-3 );
-
-    for (unsigned int fidx = 0; fidx < mesh->mNumFaces;++fidx)
-    {
-        const aiFace& face = mesh->mFaces[fidx];
-        if (face.mNumIndices < 3) continue; // triangles and polygons only, please
-
-        unsigned int small = face.mNumIndices, large = small;
-        bool zero = false, one = false, round_to_zero = false;
-
-        // Check whether this face lies on a UV seam. We can just guess,
-        // but the assumption that a face with at least one very small
-        // on the one side and one very large U coord on the other side
-        // lies on a UV seam should work for most cases.
-        for (unsigned int n = 0; n < face.mNumIndices;++n)
-        {
-            if (out[face.mIndices[n]].x < LOWER_LIMIT)
-            {
-                small = n;
-
-                // If we have a U value very close to 0 we can't
-                // round the others to 0, too.
-                if (out[face.mIndices[n]].x <= LOWER_EPSILON)
-                    zero = true;
-                else round_to_zero = true;
-            }
-            if (out[face.mIndices[n]].x > UPPER_LIMIT)
-            {
-                large = n;
-
-                // If we have a U value very close to 1 we can't
-                // round the others to 1, too.
-                if (out[face.mIndices[n]].x >= UPPER_EPSILON)
-                    one = true;
-            }
-        }
-        if (small != face.mNumIndices && large != face.mNumIndices)
-        {
-            for (unsigned int n = 0; n < face.mNumIndices;++n)
-            {
-                // If the u value is over the upper limit and no other u
-                // value of that face is 0, round it to 0
-                if (out[face.mIndices[n]].x > UPPER_LIMIT && !zero)
-                    out[face.mIndices[n]].x = 0.0;
-
-                // If the u value is below the lower limit and no other u
-                // value of that face is 1, round it to 1
-                else if (out[face.mIndices[n]].x < LOWER_LIMIT && !one)
-                    out[face.mIndices[n]].x = 1.0;
-
-                // The face contains both 0 and 1 as UV coords. This can occur
-                // for faces which have an edge that lies directly on the seam.
-                // Due to numerical inaccuracies one U coord becomes 0, the
-                // other 1. But we do still have a third UV coord to determine
-                // to which side we must round to.
-                else if (one && zero)
-                {
-                    if (round_to_zero && out[face.mIndices[n]].x >=  UPPER_EPSILON)
-                        out[face.mIndices[n]].x = 0.0;
-                    else if (!round_to_zero && out[face.mIndices[n]].x <= LOWER_EPSILON)
-                        out[face.mIndices[n]].x = 1.0;
-                }
-            }
-        }
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-void ComputeUVMappingProcess::ComputeSphereMapping(aiMesh* mesh,const aiVector3D& axis, aiVector3D* out)
-{
-    aiVector3D center, min, max;
-    FindMeshCenter(mesh, center, min, max);
-
-    // If the axis is one of x,y,z run a faster code path. It's worth the extra effort ...
-    // currently the mapping axis will always be one of x,y,z, except if the
-    // PretransformVertices step is used (it transforms the meshes into worldspace,
-    // thus changing the mapping axis)
-    if (axis * base_axis_x >= angle_epsilon)    {
-
-        // For each point get a normalized projection vector in the sphere,
-        // get its longitude and latitude and map them to their respective
-        // UV axes. Problems occur around the poles ... unsolvable.
-        //
-        // The spherical coordinate system looks like this:
-        // x = cos(lon)*cos(lat)
-        // y = sin(lon)*cos(lat)
-        // z = sin(lat)
-        //
-        // Thus we can derive:
-        // lat  = arcsin (z)
-        // lon  = arctan (y/x)
-        for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)  {
-            const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize();
-            out[pnt] = aiVector3D((std::atan2(diff.z, diff.y) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
-                (std::asin  (diff.x) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0);
-        }
-    }
-    else if (axis * base_axis_y >= angle_epsilon)   {
-        // ... just the same again
-        for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)  {
-            const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize();
-            out[pnt] = aiVector3D((std::atan2(diff.x, diff.z) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
-                (std::asin  (diff.y) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0);
-        }
-    }
-    else if (axis * base_axis_z >= angle_epsilon)   {
-        // ... just the same again
-        for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)  {
-            const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize();
-            out[pnt] = aiVector3D((std::atan2(diff.y, diff.x) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
-                (std::asin  (diff.z) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0);
-        }
-    }
-    // slower code path in case the mapping axis is not one of the coordinate system axes
-    else    {
-        aiMatrix4x4 mTrafo;
-        aiMatrix4x4::FromToMatrix(axis,base_axis_y,mTrafo);
-
-        // again the same, except we're applying a transformation now
-        for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)  {
-            const aiVector3D diff = ((mTrafo*mesh->mVertices[pnt])-center).Normalize();
-            out[pnt] = aiVector3D((std::atan2(diff.y, diff.x) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
-                (std::asin(diff.z) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0);
-        }
-    }
-
-
-    // Now find and remove UV seams. A seam occurs if a face has a tcoord
-    // close to zero on the one side, and a tcoord close to one on the
-    // other side.
-    RemoveUVSeams(mesh,out);
-}
-
-// ------------------------------------------------------------------------------------------------
-void ComputeUVMappingProcess::ComputeCylinderMapping(aiMesh* mesh,const aiVector3D& axis, aiVector3D* out)
-{
-    aiVector3D center, min, max;
-
-    // If the axis is one of x,y,z run a faster code path. It's worth the extra effort ...
-    // currently the mapping axis will always be one of x,y,z, except if the
-    // PretransformVertices step is used (it transforms the meshes into worldspace,
-    // thus changing the mapping axis)
-    if (axis * base_axis_x >= angle_epsilon)    {
-        FindMeshCenter(mesh, center, min, max);
-        const ai_real diff = max.x - min.x;
-
-        // If the main axis is 'z', the z coordinate of a point 'p' is mapped
-        // directly to the texture V axis. The other axis is derived from
-        // the angle between ( p.x - c.x, p.y - c.y ) and (1,0), where
-        // 'c' is the center point of the mesh.
-        for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)  {
-            const aiVector3D& pos = mesh->mVertices[pnt];
-            aiVector3D& uv  = out[pnt];
-
-            uv.y = (pos.x - min.x) / diff;
-            uv.x = (std::atan2( pos.z - center.z, pos.y - center.y) +(ai_real)AI_MATH_PI ) / (ai_real)AI_MATH_TWO_PI;
-        }
-    }
-    else if (axis * base_axis_y >= angle_epsilon)   {
-        FindMeshCenter(mesh, center, min, max);
-        const ai_real diff = max.y - min.y;
-
-        // just the same ...
-        for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)  {
-            const aiVector3D& pos = mesh->mVertices[pnt];
-            aiVector3D& uv  = out[pnt];
-
-            uv.y = (pos.y - min.y) / diff;
-            uv.x = (std::atan2( pos.x - center.x, pos.z - center.z) +(ai_real)AI_MATH_PI ) / (ai_real)AI_MATH_TWO_PI;
-        }
-    }
-    else if (axis * base_axis_z >= angle_epsilon)   {
-        FindMeshCenter(mesh, center, min, max);
-        const ai_real diff = max.z - min.z;
-
-        // just the same ...
-        for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)  {
-            const aiVector3D& pos = mesh->mVertices[pnt];
-            aiVector3D& uv  = out[pnt];
-
-            uv.y = (pos.z - min.z) / diff;
-            uv.x = (std::atan2( pos.y - center.y, pos.x - center.x) +(ai_real)AI_MATH_PI ) / (ai_real)AI_MATH_TWO_PI;
-        }
-    }
-    // slower code path in case the mapping axis is not one of the coordinate system axes
-    else {
-        aiMatrix4x4 mTrafo;
-        aiMatrix4x4::FromToMatrix(axis,base_axis_y,mTrafo);
-        FindMeshCenterTransformed(mesh, center, min, max,mTrafo);
-        const ai_real diff = max.y - min.y;
-
-        // again the same, except we're applying a transformation now
-        for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt){
-            const aiVector3D pos = mTrafo* mesh->mVertices[pnt];
-            aiVector3D& uv  = out[pnt];
-
-            uv.y = (pos.y - min.y) / diff;
-            uv.x = (std::atan2( pos.x - center.x, pos.z - center.z) +(ai_real)AI_MATH_PI ) / (ai_real)AI_MATH_TWO_PI;
-        }
-    }
-
-    // Now find and remove UV seams. A seam occurs if a face has a tcoord
-    // close to zero on the one side, and a tcoord close to one on the
-    // other side.
-    RemoveUVSeams(mesh,out);
-}
-
-// ------------------------------------------------------------------------------------------------
-void ComputeUVMappingProcess::ComputePlaneMapping(aiMesh* mesh,const aiVector3D& axis, aiVector3D* out)
-{
-    ai_real diffu,diffv;
-    aiVector3D center, min, max;
-
-    // If the axis is one of x,y,z run a faster code path. It's worth the extra effort ...
-    // currently the mapping axis will always be one of x,y,z, except if the
-    // PretransformVertices step is used (it transforms the meshes into worldspace,
-    // thus changing the mapping axis)
-    if (axis * base_axis_x >= angle_epsilon)    {
-        FindMeshCenter(mesh, center, min, max);
-        diffu = max.z - min.z;
-        diffv = max.y - min.y;
-
-        for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)  {
-            const aiVector3D& pos = mesh->mVertices[pnt];
-            out[pnt].Set((pos.z - min.z) / diffu,(pos.y - min.y) / diffv,0.0);
-        }
-    }
-    else if (axis * base_axis_y >= angle_epsilon)   {
-        FindMeshCenter(mesh, center, min, max);
-        diffu = max.x - min.x;
-        diffv = max.z - min.z;
-
-        for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)  {
-            const aiVector3D& pos = mesh->mVertices[pnt];
-            out[pnt].Set((pos.x - min.x) / diffu,(pos.z - min.z) / diffv,0.0);
-        }
-    }
-    else if (axis * base_axis_z >= angle_epsilon)   {
-        FindMeshCenter(mesh, center, min, max);
-        diffu = max.x - min.x;
-        diffv = max.y - min.y;
-
-        for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)  {
-            const aiVector3D& pos = mesh->mVertices[pnt];
-            out[pnt].Set((pos.x - min.x) / diffu,(pos.y - min.y) / diffv,0.0);
-        }
-    }
-    // slower code path in case the mapping axis is not one of the coordinate system axes
-    else
-    {
-        aiMatrix4x4 mTrafo;
-        aiMatrix4x4::FromToMatrix(axis,base_axis_y,mTrafo);
-        FindMeshCenterTransformed(mesh, center, min, max,mTrafo);
-        diffu = max.x - min.x;
-        diffv = max.z - min.z;
-
-        // again the same, except we're applying a transformation now
-        for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)  {
-            const aiVector3D pos = mTrafo * mesh->mVertices[pnt];
-            out[pnt].Set((pos.x - min.x) / diffu,(pos.z - min.z) / diffv,0.0);
-        }
-    }
-
-    // shouldn't be necessary to remove UV seams ...
-}
-
-// ------------------------------------------------------------------------------------------------
-void ComputeUVMappingProcess::ComputeBoxMapping( aiMesh*, aiVector3D* )
-{
-    ASSIMP_LOG_ERROR("Mapping type currently not implemented");
-}
-
-// ------------------------------------------------------------------------------------------------
-void ComputeUVMappingProcess::Execute( aiScene* pScene)
-{
-    ASSIMP_LOG_DEBUG("GenUVCoordsProcess begin");
-    char buffer[1024];
-
-    if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT)
-        throw DeadlyImportError("Post-processing order mismatch: expecting pseudo-indexed (\"verbose\") vertices here");
-
-    std::list<MappingInfo> mappingStack;
-
-    /*  Iterate through all materials and search for non-UV mapped textures
-     */
-    for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
-    {
-        mappingStack.clear();
-        aiMaterial* mat = pScene->mMaterials[i];
-        for (unsigned int a = 0; a < mat->mNumProperties;++a)
-        {
-            aiMaterialProperty* prop = mat->mProperties[a];
-            if (!::strcmp( prop->mKey.data, "$tex.mapping"))
-            {
-                aiTextureMapping& mapping = *((aiTextureMapping*)prop->mData);
-                if (aiTextureMapping_UV != mapping)
-                {
-                    if (!DefaultLogger::isNullLogger())
-                    {
-                        ai_snprintf(buffer, 1024, "Found non-UV mapped texture (%s,%u). Mapping type: %s",
-                            TextureTypeToString((aiTextureType)prop->mSemantic),prop->mIndex,
-                            MappingTypeToString(mapping));
-
-                        ASSIMP_LOG_INFO(buffer);
-                    }
-
-                    if (aiTextureMapping_OTHER == mapping)
-                        continue;
-
-                    MappingInfo info (mapping);
-
-                    // Get further properties - currently only the major axis
-                    for (unsigned int a2 = 0; a2 < mat->mNumProperties;++a2)
-                    {
-                        aiMaterialProperty* prop2 = mat->mProperties[a2];
-                        if (prop2->mSemantic != prop->mSemantic || prop2->mIndex != prop->mIndex)
-                            continue;
-
-                        if ( !::strcmp( prop2->mKey.data, "$tex.mapaxis"))  {
-                            info.axis = *((aiVector3D*)prop2->mData);
-                            break;
-                        }
-                    }
-
-                    unsigned int idx( 99999999 );
-
-                    // Check whether we have this mapping mode already
-                    std::list<MappingInfo>::iterator it = std::find (mappingStack.begin(),mappingStack.end(), info);
-                    if (mappingStack.end() != it)
-                    {
-                        idx = (*it).uv;
-                    }
-                    else
-                    {
-                        /*  We have found a non-UV mapped texture. Now
-                        *   we need to find all meshes using this material
-                        *   that we can compute UV channels for them.
-                        */
-                        for (unsigned int m = 0; m < pScene->mNumMeshes;++m)
-                        {
-                            aiMesh* mesh = pScene->mMeshes[m];
-                            unsigned int outIdx = 0;
-                            if ( mesh->mMaterialIndex != i || ( outIdx = FindEmptyUVChannel(mesh) ) == UINT_MAX ||
-                                !mesh->mNumVertices)
-                            {
-                                continue;
-                            }
-
-                            // Allocate output storage
-                            aiVector3D* p = mesh->mTextureCoords[outIdx] = new aiVector3D[mesh->mNumVertices];
-
-                            switch (mapping)
-                            {
-                            case aiTextureMapping_SPHERE:
-                                ComputeSphereMapping(mesh,info.axis,p);
-                                break;
-                            case aiTextureMapping_CYLINDER:
-                                ComputeCylinderMapping(mesh,info.axis,p);
-                                break;
-                            case aiTextureMapping_PLANE:
-                                ComputePlaneMapping(mesh,info.axis,p);
-                                break;
-                            case aiTextureMapping_BOX:
-                                ComputeBoxMapping(mesh,p);
-                                break;
-                            default:
-                                ai_assert(false);
-                            }
-                            if (m && idx != outIdx)
-                            {
-                                ASSIMP_LOG_WARN("UV index mismatch. Not all meshes assigned to "
-                                    "this material have equal numbers of UV channels. The UV index stored in  "
-                                    "the material structure does therefore not apply for all meshes. ");
-                            }
-                            idx = outIdx;
-                        }
-                        info.uv = idx;
-                        mappingStack.push_back(info);
-                    }
-
-                    // Update the material property list
-                    mapping = aiTextureMapping_UV;
-                    ((aiMaterial*)mat)->AddProperty(&idx,1,AI_MATKEY_UVWSRC(prop->mSemantic,prop->mIndex));
-                }
-            }
-        }
-    }
-    ASSIMP_LOG_DEBUG("GenUVCoordsProcess finished");
-}

+ 0 - 149
thirdparty/assimp/code/PostProcessing/ComputeUVMappingProcess.h

@@ -1,149 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file Defines a post processing step to compute UV coordinates
-  from abstract mappings, such as box or spherical*/
-#ifndef AI_COMPUTEUVMAPPING_H_INC
-#define AI_COMPUTEUVMAPPING_H_INC
-
-#include "Common/BaseProcess.h"
-
-#include <assimp/mesh.h>
-#include <assimp/material.h>
-#include <assimp/types.h>
-
-class ComputeUVMappingTest;
-
-namespace Assimp {
-
-// ---------------------------------------------------------------------------
-/** ComputeUVMappingProcess - converts special mappings, such as spherical,
- *  cylindrical or boxed to proper UV coordinates for rendering.
-*/
-class ComputeUVMappingProcess : public BaseProcess
-{
-public:
-    ComputeUVMappingProcess();
-    ~ComputeUVMappingProcess();
-
-public:
-
-    // -------------------------------------------------------------------
-    /** Returns whether the processing step is present in the given flag field.
-    * @param pFlags The processing flags the importer was called with. A bitwise
-    *   combination of #aiPostProcessSteps.
-    * @return true if the process is present in this flag fields, false if not.
-    */
-    bool IsActive( unsigned int pFlags) const;
-
-    // -------------------------------------------------------------------
-    /** Executes the post processing step on the given imported data.
-    * At the moment a process is not supposed to fail.
-    * @param pScene The imported data to work at.
-    */
-    void Execute( aiScene* pScene);
-
-protected:
-
-    // -------------------------------------------------------------------
-    /** Computes spherical UV coordinates for a mesh
-     *
-     *  @param mesh Mesh to be processed
-     *  @param axis Main axis
-     *  @param out Receives output UV coordinates
-    */
-    void ComputeSphereMapping(aiMesh* mesh,const aiVector3D& axis,
-        aiVector3D* out);
-
-    // -------------------------------------------------------------------
-    /** Computes cylindrical UV coordinates for a mesh
-     *
-     *  @param mesh Mesh to be processed
-     *  @param axis Main axis
-     *  @param out Receives output UV coordinates
-    */
-    void ComputeCylinderMapping(aiMesh* mesh,const aiVector3D& axis,
-        aiVector3D* out);
-
-    // -------------------------------------------------------------------
-    /** Computes planar UV coordinates for a mesh
-     *
-     *  @param mesh Mesh to be processed
-     *  @param axis Main axis
-     *  @param out Receives output UV coordinates
-    */
-    void ComputePlaneMapping(aiMesh* mesh,const aiVector3D& axis,
-        aiVector3D* out);
-
-    // -------------------------------------------------------------------
-    /** Computes cubic UV coordinates for a mesh
-     *
-     *  @param mesh Mesh to be processed
-     *  @param out Receives output UV coordinates
-    */
-    void ComputeBoxMapping(aiMesh* mesh, aiVector3D* out);
-
-private:
-
-    // temporary structure to describe a mapping
-    struct MappingInfo
-    {
-        explicit MappingInfo(aiTextureMapping _type)
-            : type  (_type)
-            , axis  (0.f,1.f,0.f)
-            , uv    (0u)
-        {}
-
-        aiTextureMapping type;
-        aiVector3D axis;
-        unsigned int uv;
-
-        bool operator== (const MappingInfo& other)
-        {
-            return type == other.type && axis == other.axis;
-        }
-    };
-};
-
-} // end of namespace Assimp
-
-#endif // AI_COMPUTEUVMAPPING_H_INC

+ 0 - 414
thirdparty/assimp/code/PostProcessing/ConvertToLHProcess.cpp

@@ -1,414 +0,0 @@
-/*
----------------------------------------------------------------------------
-Open Asset Import Library (assimp)
----------------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the following
-conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------------
-*/
-
-/** @file  MakeLeftHandedProcess.cpp
- *  @brief Implementation of the post processing step to convert all
- *  imported data to a left-handed coordinate system.
- *
- *  Face order & UV flip are also implemented here, for the sake of a
- *  better location.
- */
-
-
-#include "ConvertToLHProcess.h"
-#include <assimp/scene.h>
-#include <assimp/postprocess.h>
-#include <assimp/DefaultLogger.hpp>
-
-using namespace Assimp;
-
-#ifndef ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS
-
-namespace {
-
-template <typename aiMeshType>
-void flipUVs(aiMeshType* pMesh) {
-    if (pMesh == nullptr) { return; }
-    // mirror texture y coordinate
-    for (unsigned int tcIdx = 0; tcIdx < AI_MAX_NUMBER_OF_TEXTURECOORDS; tcIdx++) {
-        if (!pMesh->HasTextureCoords(tcIdx)) {
-            break;
-        }
-
-        for (unsigned int vIdx = 0; vIdx < pMesh->mNumVertices; vIdx++) {
-            pMesh->mTextureCoords[tcIdx][vIdx].y = 1.0f - pMesh->mTextureCoords[tcIdx][vIdx].y;
-        }
-    }
-}
-
-} // namespace
-
-// ------------------------------------------------------------------------------------------------
-// Constructor to be privately used by Importer
-MakeLeftHandedProcess::MakeLeftHandedProcess()
-: BaseProcess() {
-    // empty
-}
-
-// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
-MakeLeftHandedProcess::~MakeLeftHandedProcess() {
-    // empty
-}
-
-// ------------------------------------------------------------------------------------------------
-// Returns whether the processing step is present in the given flag field.
-bool MakeLeftHandedProcess::IsActive( unsigned int pFlags) const
-{
-    return 0 != (pFlags & aiProcess_MakeLeftHanded);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Executes the post processing step on the given imported data.
-void MakeLeftHandedProcess::Execute( aiScene* pScene)
-{
-    // Check for an existent root node to proceed
-    ai_assert(pScene->mRootNode != NULL);
-    ASSIMP_LOG_DEBUG("MakeLeftHandedProcess begin");
-
-    // recursively convert all the nodes
-    ProcessNode( pScene->mRootNode, aiMatrix4x4());
-
-    // process the meshes accordingly
-    for ( unsigned int a = 0; a < pScene->mNumMeshes; ++a ) {
-        ProcessMesh( pScene->mMeshes[ a ] );
-    }
-
-    // process the materials accordingly
-    for ( unsigned int a = 0; a < pScene->mNumMaterials; ++a ) {
-        ProcessMaterial( pScene->mMaterials[ a ] );
-    }
-
-    // transform all animation channels as well
-    for( unsigned int a = 0; a < pScene->mNumAnimations; a++)
-    {
-        aiAnimation* anim = pScene->mAnimations[a];
-        for( unsigned int b = 0; b < anim->mNumChannels; b++)
-        {
-            aiNodeAnim* nodeAnim = anim->mChannels[b];
-            ProcessAnimation( nodeAnim);
-        }
-    }
-    ASSIMP_LOG_DEBUG("MakeLeftHandedProcess finished");
-}
-
-// ------------------------------------------------------------------------------------------------
-// Recursively converts a node, all of its children and all of its meshes
-void MakeLeftHandedProcess::ProcessNode( aiNode* pNode, const aiMatrix4x4& pParentGlobalRotation)
-{
-    // mirror all base vectors at the local Z axis
-    pNode->mTransformation.c1 = -pNode->mTransformation.c1;
-    pNode->mTransformation.c2 = -pNode->mTransformation.c2;
-    pNode->mTransformation.c3 = -pNode->mTransformation.c3;
-    pNode->mTransformation.c4 = -pNode->mTransformation.c4;
-
-    // now invert the Z axis again to keep the matrix determinant positive.
-    // The local meshes will be inverted accordingly so that the result should look just fine again.
-    pNode->mTransformation.a3 = -pNode->mTransformation.a3;
-    pNode->mTransformation.b3 = -pNode->mTransformation.b3;
-    pNode->mTransformation.c3 = -pNode->mTransformation.c3;
-    pNode->mTransformation.d3 = -pNode->mTransformation.d3; // useless, but anyways...
-
-    // continue for all children
-    for( size_t a = 0; a < pNode->mNumChildren; ++a ) {
-        ProcessNode( pNode->mChildren[ a ], pParentGlobalRotation * pNode->mTransformation );
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-// Converts a single mesh to left handed coordinates.
-void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh) {
-    if ( nullptr == pMesh ) {
-        ASSIMP_LOG_ERROR( "Nullptr to mesh found." );
-        return;
-    }
-    // mirror positions, normals and stuff along the Z axis
-    for( size_t a = 0; a < pMesh->mNumVertices; ++a)
-    {
-        pMesh->mVertices[a].z *= -1.0f;
-        if (pMesh->HasNormals()) {
-            pMesh->mNormals[a].z *= -1.0f;
-        }
-        if( pMesh->HasTangentsAndBitangents())
-        {
-            pMesh->mTangents[a].z *= -1.0f;
-            pMesh->mBitangents[a].z *= -1.0f;
-        }
-    }
-
-    // mirror anim meshes positions, normals and stuff along the Z axis
-    for (size_t m = 0; m < pMesh->mNumAnimMeshes; ++m)
-    {
-        for (size_t a = 0; a < pMesh->mAnimMeshes[m]->mNumVertices; ++a)
-        {
-            pMesh->mAnimMeshes[m]->mVertices[a].z *= -1.0f;
-            if (pMesh->mAnimMeshes[m]->HasNormals()) {
-                pMesh->mAnimMeshes[m]->mNormals[a].z *= -1.0f;
-            }
-            if (pMesh->mAnimMeshes[m]->HasTangentsAndBitangents())
-            {
-                pMesh->mAnimMeshes[m]->mTangents[a].z *= -1.0f;
-                pMesh->mAnimMeshes[m]->mBitangents[a].z *= -1.0f;
-            }
-        }
-    }
-
-    // mirror offset matrices of all bones
-    for( size_t a = 0; a < pMesh->mNumBones; ++a)
-    {
-        aiBone* bone = pMesh->mBones[a];
-        bone->mOffsetMatrix.a3 = -bone->mOffsetMatrix.a3;
-        bone->mOffsetMatrix.b3 = -bone->mOffsetMatrix.b3;
-        bone->mOffsetMatrix.d3 = -bone->mOffsetMatrix.d3;
-        bone->mOffsetMatrix.c1 = -bone->mOffsetMatrix.c1;
-        bone->mOffsetMatrix.c2 = -bone->mOffsetMatrix.c2;
-        bone->mOffsetMatrix.c4 = -bone->mOffsetMatrix.c4;
-    }
-
-    // mirror bitangents as well as they're derived from the texture coords
-    if( pMesh->HasTangentsAndBitangents())
-    {
-        for( unsigned int a = 0; a < pMesh->mNumVertices; a++)
-            pMesh->mBitangents[a] *= -1.0f;
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-// Converts a single material to left handed coordinates.
-void MakeLeftHandedProcess::ProcessMaterial( aiMaterial* _mat) {
-    if ( nullptr == _mat ) {
-        ASSIMP_LOG_ERROR( "Nullptr to aiMaterial found." );
-        return;
-    }
-
-    aiMaterial* mat = (aiMaterial*)_mat;
-    for (unsigned int a = 0; a < mat->mNumProperties;++a)   {
-        aiMaterialProperty* prop = mat->mProperties[a];
-
-        // Mapping axis for UV mappings?
-        if (!::strcmp( prop->mKey.data, "$tex.mapaxis"))    {
-            ai_assert( prop->mDataLength >= sizeof(aiVector3D)); /* something is wrong with the validation if we end up here */
-            aiVector3D* pff = (aiVector3D*)prop->mData;
-            pff->z *= -1.f;
-        }
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-// Converts the given animation to LH coordinates.
-void MakeLeftHandedProcess::ProcessAnimation( aiNodeAnim* pAnim)
-{
-    // position keys
-    for( unsigned int a = 0; a < pAnim->mNumPositionKeys; a++)
-        pAnim->mPositionKeys[a].mValue.z *= -1.0f;
-
-    // rotation keys
-    for( unsigned int a = 0; a < pAnim->mNumRotationKeys; a++)
-    {
-        /* That's the safe version, but the float errors add up. So we try the short version instead
-        aiMatrix3x3 rotmat = pAnim->mRotationKeys[a].mValue.GetMatrix();
-        rotmat.a3 = -rotmat.a3; rotmat.b3 = -rotmat.b3;
-        rotmat.c1 = -rotmat.c1; rotmat.c2 = -rotmat.c2;
-        aiQuaternion rotquat( rotmat);
-        pAnim->mRotationKeys[a].mValue = rotquat;
-        */
-        pAnim->mRotationKeys[a].mValue.x *= -1.0f;
-        pAnim->mRotationKeys[a].mValue.y *= -1.0f;
-    }
-}
-
-#endif // !!  ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS
-#ifndef  ASSIMP_BUILD_NO_FLIPUVS_PROCESS
-// # FlipUVsProcess
-
-// ------------------------------------------------------------------------------------------------
-// Constructor to be privately used by Importer
-FlipUVsProcess::FlipUVsProcess()
-{}
-
-// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
-FlipUVsProcess::~FlipUVsProcess()
-{}
-
-// ------------------------------------------------------------------------------------------------
-// Returns whether the processing step is present in the given flag field.
-bool FlipUVsProcess::IsActive( unsigned int pFlags) const
-{
-    return 0 != (pFlags & aiProcess_FlipUVs);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Executes the post processing step on the given imported data.
-void FlipUVsProcess::Execute( aiScene* pScene)
-{
-    ASSIMP_LOG_DEBUG("FlipUVsProcess begin");
-    for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
-        ProcessMesh(pScene->mMeshes[i]);
-
-    for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
-        ProcessMaterial(pScene->mMaterials[i]);
-    ASSIMP_LOG_DEBUG("FlipUVsProcess finished");
-}
-
-// ------------------------------------------------------------------------------------------------
-// Converts a single material
-void FlipUVsProcess::ProcessMaterial (aiMaterial* _mat)
-{
-    aiMaterial* mat = (aiMaterial*)_mat;
-    for (unsigned int a = 0; a < mat->mNumProperties;++a)   {
-        aiMaterialProperty* prop = mat->mProperties[a];
-        if( !prop ) {
-            ASSIMP_LOG_DEBUG( "Property is null" );
-            continue;
-        }
-
-        // UV transformation key?
-        if (!::strcmp( prop->mKey.data, "$tex.uvtrafo"))    {
-            ai_assert( prop->mDataLength >= sizeof(aiUVTransform));  /* something is wrong with the validation if we end up here */
-            aiUVTransform* uv = (aiUVTransform*)prop->mData;
-
-            // just flip it, that's everything
-            uv->mTranslation.y *= -1.f;
-            uv->mRotation *= -1.f;
-        }
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-// Converts a single mesh
-void FlipUVsProcess::ProcessMesh( aiMesh* pMesh)
-{
-    flipUVs(pMesh);
-    for (unsigned int idx = 0; idx < pMesh->mNumAnimMeshes; idx++) {
-        flipUVs(pMesh->mAnimMeshes[idx]);
-    }
-}
-
-#endif // !ASSIMP_BUILD_NO_FLIPUVS_PROCESS
-#ifndef  ASSIMP_BUILD_NO_FLIPWINDING_PROCESS
-// # FlipWindingOrderProcess
-
-// ------------------------------------------------------------------------------------------------
-// Constructor to be privately used by Importer
-FlipWindingOrderProcess::FlipWindingOrderProcess()
-{}
-
-// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
-FlipWindingOrderProcess::~FlipWindingOrderProcess()
-{}
-
-// ------------------------------------------------------------------------------------------------
-// Returns whether the processing step is present in the given flag field.
-bool FlipWindingOrderProcess::IsActive( unsigned int pFlags) const
-{
-    return 0 != (pFlags & aiProcess_FlipWindingOrder);
-}
-
-// ------------------------------------------------------------------------------------------------
-// Executes the post processing step on the given imported data.
-void FlipWindingOrderProcess::Execute( aiScene* pScene)
-{
-    ASSIMP_LOG_DEBUG("FlipWindingOrderProcess begin");
-    for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
-        ProcessMesh(pScene->mMeshes[i]);
-    ASSIMP_LOG_DEBUG("FlipWindingOrderProcess finished");
-}
-
-// ------------------------------------------------------------------------------------------------
-// Converts a single mesh
-void FlipWindingOrderProcess::ProcessMesh( aiMesh* pMesh)
-{
-    // invert the order of all faces in this mesh
-    for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
-    {
-        aiFace& face = pMesh->mFaces[a];
-        for (unsigned int b = 0; b < face.mNumIndices / 2; b++) {
-            std::swap(face.mIndices[b], face.mIndices[face.mNumIndices - 1 - b]);
-        }
-    }
-
-    // invert the order of all components in this mesh anim meshes
-    for (unsigned int m = 0; m < pMesh->mNumAnimMeshes; m++) {
-        aiAnimMesh* animMesh = pMesh->mAnimMeshes[m];
-        unsigned int numVertices = animMesh->mNumVertices;
-        if (animMesh->HasPositions()) {
-            for (unsigned int a = 0; a < numVertices; a++)
-            {
-                std::swap(animMesh->mVertices[a], animMesh->mVertices[numVertices - 1 - a]);
-            }
-        }
-        if (animMesh->HasNormals()) {
-            for (unsigned int a = 0; a < numVertices; a++)
-            {
-                std::swap(animMesh->mNormals[a], animMesh->mNormals[numVertices - 1 - a]);
-            }
-        }
-        for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; i++) {
-            if (animMesh->HasTextureCoords(i)) {
-                for (unsigned int a = 0; a < numVertices; a++)
-                {
-                    std::swap(animMesh->mTextureCoords[i][a], animMesh->mTextureCoords[i][numVertices - 1 - a]);
-                }
-            }
-        }
-        if (animMesh->HasTangentsAndBitangents()) {
-            for (unsigned int a = 0; a < numVertices; a++)
-            {
-                std::swap(animMesh->mTangents[a], animMesh->mTangents[numVertices - 1 - a]);
-                std::swap(animMesh->mBitangents[a], animMesh->mBitangents[numVertices - 1 - a]);
-            }
-        }
-        for (unsigned int v = 0; v < AI_MAX_NUMBER_OF_COLOR_SETS; v++) {
-            if (animMesh->HasVertexColors(v)) {
-                for (unsigned int a = 0; a < numVertices; a++)
-                {
-                    std::swap(animMesh->mColors[v][a], animMesh->mColors[v][numVertices - 1 - a]);
-                }
-            }
-        }
-    }
-}
-
-#endif // !! ASSIMP_BUILD_NO_FLIPWINDING_PROCESS

+ 0 - 171
thirdparty/assimp/code/PostProcessing/ConvertToLHProcess.h

@@ -1,171 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2019, assimp team
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-*/
-
-/** @file  MakeLeftHandedProcess.h
- *  @brief Defines a bunch of post-processing steps to handle
- *    coordinate system conversions.
- *
- *  - LH to RH
- *  - UV origin upper-left to lower-left
- *  - face order cw to ccw
- */
-#ifndef AI_CONVERTTOLHPROCESS_H_INC
-#define AI_CONVERTTOLHPROCESS_H_INC
-
-#include <assimp/types.h>
-
-#include "Common/BaseProcess.h"
-
-struct aiMesh;
-struct aiNodeAnim;
-struct aiNode;
-struct aiMaterial;
-
-namespace Assimp    {
-
-// -----------------------------------------------------------------------------------
-/** @brief The MakeLeftHandedProcess converts all imported data to a left-handed
- *   coordinate system.
- *
- * This implies a mirroring of the Z axis of the coordinate system. But to keep
- * transformation matrices free from reflections we shift the reflection to other
- * places. We mirror the meshes and adapt the rotations.
- *
- * @note RH-LH and LH-RH is the same, so this class can be used for both
- */
-class MakeLeftHandedProcess : public BaseProcess
-{
-
-
-public:
-    MakeLeftHandedProcess();
-    ~MakeLeftHandedProcess();
-
-    // -------------------------------------------------------------------
-    bool IsActive( unsigned int pFlags) const;
-
-    // -------------------------------------------------------------------
-    void Execute( aiScene* pScene);
-
-protected:
-
-    // -------------------------------------------------------------------
-    /** Recursively converts a node and all of its children
-     */
-    void ProcessNode( aiNode* pNode, const aiMatrix4x4& pParentGlobalRotation);
-
-    // -------------------------------------------------------------------
-    /** Converts a single mesh to left handed coordinates.
-     * This means that positions, normals and tangents are mirrored at
-     * the local Z axis and the order of all faces are inverted.
-     * @param pMesh The mesh to convert.
-     */
-    void ProcessMesh( aiMesh* pMesh);
-
-    // -------------------------------------------------------------------
-    /** Converts a single material to left-handed coordinates
-     * @param pMat Material to convert
-     */
-    void ProcessMaterial( aiMaterial* pMat);
-
-    // -------------------------------------------------------------------
-    /** Converts the given animation to LH coordinates.
-     * The rotation and translation keys are transformed, the scale keys
-     * work in local space and can therefore be left untouched.
-     * @param pAnim The bone animation to transform
-     */
-    void ProcessAnimation( aiNodeAnim* pAnim);
-};
-
-
-// ---------------------------------------------------------------------------
-/** Postprocessing step to flip the face order of the imported data
- */
-class FlipWindingOrderProcess : public BaseProcess
-{
-    friend class Importer;
-
-public:
-    /** Constructor to be privately used by Importer */
-    FlipWindingOrderProcess();
-
-    /** Destructor, private as well */
-    ~FlipWindingOrderProcess();
-
-    // -------------------------------------------------------------------
-    bool IsActive( unsigned int pFlags) const;
-
-    // -------------------------------------------------------------------
-    void Execute( aiScene* pScene);
-
-protected:
-    void ProcessMesh( aiMesh* pMesh);
-};
-
-// ---------------------------------------------------------------------------
-/** Postprocessing step to flip the UV coordinate system of the import data
- */
-class FlipUVsProcess : public BaseProcess
-{
-    friend class Importer;
-
-public:
-    /** Constructor to be privately used by Importer */
-    FlipUVsProcess();
-
-    /** Destructor, private as well */
-    ~FlipUVsProcess();
-
-    // -------------------------------------------------------------------
-    bool IsActive( unsigned int pFlags) const;
-
-    // -------------------------------------------------------------------
-    void Execute( aiScene* pScene);
-
-protected:
-    void ProcessMesh( aiMesh* pMesh);
-    void ProcessMaterial( aiMaterial* mat);
-};
-
-} // end of namespace Assimp
-
-#endif // AI_CONVERTTOLHPROCESS_H_INC

Some files were not shown because too many files changed in this diff